We have multitenant asp.net MVC web site which supports multiple partners. Currently we are using forms authentication to authenticate users. Now some of the partners have asked for single sign on support with SAML.
I did quick POC to test it against “Thinktecture” identity provider. All I did was to install “Identity and access” extension for VS 2012 and configure the identity provider. I noticed that the extension added configuration settings like URL of the IP and realm in the web.config file. It also added “WSFederationAuthenticationModule” module to handle the authentication. This module was handling all the redirects and the validation of response behind the scene.
In my case since we will have multiple identity providers, depending upon the partner, I will be choosing the Identity provider. The URLs of the different IPs will be stored in the database. I cannot list all the IPs in web.config. Hence I need mechanism in which I can redirect user to appropriate IP URL and once the IP posts back the result, verify the result and retrieve user information through claims. I don’t want to do the XML parsing of the result and validate the response, but just want to call methods in “WSFederationAuthenticationModule” to do the heavy duty work. But I am not sure which methods will be useful for me. Can somebody help me out or list of the sequence of methods I need to execute to achieve this?
Take a look at my simple example
http://www.wiktorzychla.com/2014/11/simplest-saml11-federated-authentication.html
The trick is not to have the WSFam module in the pipleline but rather use its api to trigger redirects and consume responses. If you follow my code, you'll see there are two clauses
// wsfed response or not
if ( !fam.IsSignInResponse(...) )
// redirect to provider
else
// create local config and validate the incoming token
This simple example is perfectly suitable for multitenant scenario, in fact we use ws-fed daily in multitenant environment and most clients are based on this core approach.
Namely, creating the SecurityTokenHandlerConfiguration programatically in the branch that consumes the response gives you total control over how you validate tokens for different tenants.
Related
I work for a company that supports many applications, but for ease for users has an OAuth OIDC Single-Sign-On (IdentityServer4) so they can log in once and access many applications of ours. I have no problem configuring authorization to this OAuth with the returned JWT/Access Token.
But because our support footprint is so large, we have been told to handle roles, and user permissions at the application level. Here is where I am asking for feedback. I am currently developing a new API in .Net Core 6 (newbie to building APIs), and am wondering best practice for connecting a essentially third party OAuth, but also utilizing roles and permissions specific to the application.
The Identity Server returns a JWT/Access Token that is passed to API in form of bearer, but I need a mapping on the .net core backend to map the User contained in the JWT with a user within the application. Then the application can have separate mappings for roles/permissions, and utilize those roles as restrictions within the API, but I am not sure what best practice would be for this that also maintains the best security, while also achieving best performance. My thought was creating a middleware that creates and overrides userIdentity, but with that happening each call seems like unnecessary overhead. The other option is dual auth with cookie based auth that is set once, but am just unsure of best way, or what others have had success with. I know this must be a common flow that I am overthinking. Any insight is greatly appreciated.
It is common in many mature business systems to integrate identity and business data as you describe. There are two main techniques:
Identity system reaches out to business data at the time of token issuance, to get custom claims to include in access tokens. This Curity article explains the approach.
APIs look up custom claims, eg from a database, when an access token is first received, then cache custom claims for subsequent requests with the same access token. See this .NET code of mine for one way to do this.
In both cases the end result should be that the API business logic gets a useful ClaimsPrincipal that enables the correct authorization, as in this example class.
Finally, from an information disclosure viewpoint, aim to avoid returning detailed claims in JWTs to internet clients. It is common to use opaque access tokens instead, as a privacy preserving pattern.
I have an Angular Single Page Application (SPA) talking to my ASP.NET API.
The API is protected by my own Oauth2 server (IdentityServer4).
One of my customers (let's call him X) wants SSO: Their users on my platform would sign in on their server instead of using the login form in my app that connects to my IdentityServer.
Each customer has its own subdomain for the Angular SPA (e.g. x.myapp.com). Therefore I can easily redirect X's users to their server's authorization page to approve my API, based on the hostname.
However the API itself uses one common hostname for all customers(api.myapp.com). Customers are distinguished by the Origin header of the API call (x.myapp.com) during the login call (and a few other unprotected calls) and by the Bearer token for protected calls to the API.
How does my API introspect the Bearer access token? Who should know which server to query ?
Is it the responsibility of the API server? Or can I tell my IdentityServer about X's oauth2 server ?
X's users would also be defined on my platform since we need specific info (such as config of roles on the platform). My current setup implies specific claims (such as user id) that allow my API to know what the user can do. Obviously, X's server will not provide the same claims. How can I connect the dots ? e.g. get some standard claim from X's server (username, email, whatever) and match it to my list of users.
Note: This question is similar but the answer is not accepted and seems to imply that the provider of both identity servers is the same (not the case here).
Formatting my comments as an answer:
From reading your question it's pretty much clear to me that you could benefit from what is know as Federated identity.
As you said, one of your customer want to achieve SSO - They want users to login using their existing accounts and be able to user your systems normally.
Since you already have an IdentityServer in your domain, what you can do is delegate the login part to the customer's side (whatever they do it). This is illustrated in the Identity server documentation Federation Gateway.
Basically, the approach is that upon hitting the "login" button in your front-end, you would redirect the users to your Identity Server passing some special params (prompt and acr_values for ex) which in turn, tells identity server to redirect the user's to the external Identity provider (the customer's). After a successful login, you have a chance in Identity Server to augment the claims, maybe using something they returned or anything really. Then the process is as normal - you return a JWT Token generated by your Identity Server
The benefit of doing this is:
Your SPA/API doesn't have to change. You will still work with your own bearer tokens and can continue doing authN/AuthZ as before.
You have a chance to add claims that might indicate where this user is coming from if needed
If your customer's server changes, you don't have to worry much, apart from maybe some tweaks related to returned claims
They don't necessarily need to use OpenId/OAuth on their side for this to work
Useful things you probably will need is some params to pass during the call to the authorize endpoint in Identity Server. (acr_values and prompt).
You can also check this in the quickstarts, by looking at Sign-in with external providers (which is pretty similar to what you want)
Now to your individual points:
Your Identity Server should be the "bridge" between you and the customer's "identity provider".
Upon a login from an external provider (X), you need to somehow identify the user on your platform. You could use email or, even better, if X is already using OpenId/OAuth they might give you the sub claim which is the user id on their side. At this point you need some sort of agreement with them otherwise this might be flaky/unreliable for both sides.
In a more "advanced note" you could also add to your tokens some sort of claim that tells you who is the source provider of this user. Here the source provider would be X. This is useful because you might want, for example, configure allowed identity providers in your app, or maybe enable features only for certain providers. Like, ppl logging in with Google might only see certain parts of the app.
We're looking for 3 types of different access levels but don't know how to implement them using current identityserver4 features.
Have these scenarios:
We have an upper management system which some clients have access to specific pages or not, like admin or client(seems like Roles)
We have column type access level, for example, some users in the manager role can see a specific column/field or not, or in same roles shouldn't see some column/row data in reports.
We have a record level, access level, for example, some manager shouldn't see other branch client list. (like policies)
The whole process should be dynamic without any hardcode. and for doing these structures we should do some code on the back-end(middleware, etc) and some on frontend side(with a razor or etc).
any Idea how to implement these using identityserver4 authorization types?
The main feature of IdentityServer is to handle the authentication of the user and global authorization: which client has access to what resource.
Everything else could be considered out-of-scope of IdentityServer. Please read this article for some background information.
As an answer they've created the PolicyServer.
In the OSS version authorization has become a seperate (local) mechanism, while the paid version outsources authorization to a seperate server.
Extended with resource-based authorization you can implement authorization that covers all access levels.
I am currently using Token based authorization via OWIN to keep my APIs from being exposed to everybody.
However, there is a flaw attached to this method. Once a user gets a token, he can access any API across my website and get the response for any parameters posted; which is dangerous in my case.
Right now, I need to give API access to my mobile application but I want to strengthen the security of my APIs in such a way that the requests are filtered based on user access.
Use case:
I generate a token when the user logs in and will append it with each request to the API. It works absolutely fine but... the generated token can be used to fetch the details of any other user.
What I want to achieve:
I want to prevent the above case from happening. I want to filter the illegal requests/responses to/from API.
How do I go about it? How do mobile apps generally restrict users from accessing their API. I am very interested to know about it. Please guide me.
What you have implemented till now is only authentication part, it is not going to help you much for securing your website, to implement security in proper way you need to do proper authorization also.
For this you need to implement following things.
RBAC - Role Based Access Control in your web api actions, by this you can achieved using the default Authorize filter provided by the framework.
For example
[Authorize(Roles = "Administrator")]
public void DoSomething()
{
}
If you are using OWIN, you can set the roles in GrantResourceOwnerCredentials method like following
identity.AddClaim(new Claim(ClaimTypes.Role, "Administrator"));
Data Level Security: This is very important, as people belonging to same role can access only a set of data, to implement this type of security, the best place is your database. You can implement Row Level Security/Cell Level Security in your database, or you can restrict the access of data based on logged in user from your database directly.
Implementing Data Level Security is not straight forward as it is driven through your business requirements (Who can access what). Out of the box no framework will be able to give you complete solution, you need to implement rules by yourself only.
Apart from above two points, you can also consider looking Cross-Site Request Forgery (CSRF) and Data integrity between server and client.
I'm using VS2013 and Web API 2 to create a self-hosted (using OWIN), RESTful service over SSL using token authentication. Although I'm not a novice developer, this is my first time looking at ASP.NET technologies, so please keep that in mind.
I've got everything more-or-less working except for the authentication and authorisation parts. I fully understand the difference of authenticating a user (who is this user?) and authorising an already authenticated user to access a resource (can this user access this particular resource?).
A very simple overview of my auth process is as follows (makes some assumptions for brevity):
An unknown client connects to the API, e.g. GET api/values.
The server responds with a 401 and this response header: "WWW-Authenticate: Token".
Upon seeing this, the unknown client knows to connect to a different API endpoint here: POST api/auth (routed to the Login function), supplying the username and password.
The server will try to figure out if this is a valid user and can accept or reject the user depending on the validity of the credentials.
(Rejected) The server returns an error status code (403?). End of process.
(Accepted) The server creates a random token (e.g. a GUID) and stores it against the user record. Then it sends the token to the client.
The now authenticated client reconnects to the API, GET api/values, and this time also supplies the token.
The user returns the resource data to the client.
...
The user can log out by connecting to the same API as he used to log in: POST api/auth (this time, his request will be routed to the Logout function). This will remove the token from the server and the client will also have to remove its own token.
As you can see, this is a relatively simple process, but I can't find any concrete and simple examples to understand how best to achieve this with a self-hosted Web API 2.
I don't need to register users or do any password/roles management, etc. and there is no external authentication. All valid users have the same rights to access the resources and they're already created in the system by a separate process over which I have no control (I can only read their credentials for validation). Most examples I found are talking about security frameworks that I don't need, so I've ruled out using any of the following: Basic Authentication, Windows Authentication, Forms Authentication, Individual Accounts, ASP.NET Membership/Identity, OAuth, Thinktecture or any other security framework.
I've read articles about authenticating in a message handler and others about authentication in a custom Authorize attribute filter, while others even suggest I should use the new (in Web API 2) IAuthenticateFilter attribute. This is very confusing. Can you please advise on a very simple way to achieve my auth objectives? Any specific code examples will be greatly appreciated, even if they're just skeleton implementation or pseudocode. I just need some ideas to get me started.
After a lot of googling, I found this article on CodeProject: http://www.codeproject.com/Articles/630986/Cross-Platform-Authentication-With-ASP-NET-Web-API. While this is not Web API 2 or self-hosted, it has given me a number of ideas on how to proceed.
Someone also posted a comment to that CodeProject article referencing a NuGet package that may interest anyone looking for something similar: https://www.nuget.org/packages/WebApiTokenAuth. In my case, it is a bit much.
Finally, in addition to the authentication options mentioned in the question, there's also the option to write an OWIN middleware to do authentication if self-hosting using OWIN (as per the official MS recommendation). However, I plan to implement this particular form of token authentication with a message handler, as there's more support for this method available than for writing OWIN middleware.