How to forward claims from external provider to requesting application - openiddict

We are successfully using the openiddict support for external providers (in our pilot case Azure AD). See image for external provider claims in this example.
The external provider redirects to /Account/ExternalLoginCallback where the external provider claims are available, and the method ends with redirecting to connect/authorize (thats internally calls CreateTicket).
There we have no access longer to the external provider claims, that we simply would like to return to the calling application, e g "name" and "preferred_username".
Please guide us for this flow.
A work around could of course be to save all wanted information from claims in the database on our extended IdentityUser class and then retrieve the information later in the flow. But we want to avoid that, we see no meening to store the information we simply want to forward. Keep storage simple.

Related

OAuth implementation including login using internal database

I want to include the oauth2 authentication flow into my application, but also provide an internal database (regular register / login) as an authentication method.
I'm not that sure how to approach that behavior, as I would love to have one single state for the authentication. I've thought about exposing the authentication using the internal database as an OAuth2 application itself, therefor token management etc can be generalized.
This would be a basic example of my thought process:
To distinguish between the multiple OAuth providers, I'd have wrapped the actual token inside a JWT, which also contains the providers name (as well as have a spam protection in my backend, instead of spamming the actual provider).
I'm not sure if it's that good to store the actual user data in a database as well - But I'd need some kind of overview of registered users for the administrators to see - and maybe block or delete.
My questions in particular:
Should the OAuth token be wrapped in a JWT for identification of the provider?
Is it bad practice to store the user data in a database as well? (If not, how much data should be stored [username, ...] and when should the data be refreshed?)
Is there anything else I should keep in mind when doing the authentication flow as it is?

IdentityServer4 personal access token (github-like) or API key for third party clients

Our current setup is
IdentityServer4
Angular + ASP.NET Core application
Authentication for the app via implicit flow/oidc.
We want to provide APIs for customers, i.e. third party clients, with restricted access (separate set/subset of claims). These clients are mostly non-interactive scripts that download data.
This means that we cannot use any flow which (occasionally) requires user interaction. Personal access tokens, like in github, or some other generate once, reuse for a long time API key or token would be needed.
The long token lifetime would not be a security issue, because the token should only allow access to a few read-only APIs and only for that customer's data - so the responsibility to handle the token(s) falls onto the customer.
The customer should be able to create and revoke such API-access tokens based on their claims. Some users might only claims to access certain APIs.
It would be good if we could later prevent that the user re-uses the same token for multiple clients because of licensing requirements but that is perhaps an entirely new question
How could I achieve this?
I thought about doing this via a custom grant, similar to a delegation grant: user uses app, which calls the asp.net core API, which performs auth with that custom grant, persists that token somewhere (just a plain table in the database full of customer-api-only tokens? I'm not sure about that) and shows it to the user - which can also retrieve it later from storage.
I'm thinking about doing the "delegate"-authentication via our API so that we don't leak the secrets into the Angular application.
I think that we then should be able to have either long-lived access tokens or at least refresh tokens via that custom grant.
2017-12-12 how I think I could solve it
We want a process where the user generates something in our application (i.e. via our client) and this something can later be used by the user's third party client to access the API - or request an access token and then access the API.
We want this access to be tied to the user. This includes
- Disabled user
- Lockout
- Specific claims (e.g. tenant)
This does not lend itself well to a solution that issues access tokens directly, because the token would remain valid even if the user was disabled or locked out. Which means that we cannot use a custom grant or IdentityServerTools to issue tokens directly.
Therefore we should use the client credentials grant, or something similar to it, as this could yield new, short-lived access tokens.
User actually generates a new client, which is pre-filled with claims from the user (such as the tenant - which is immutable) and has a claim that corresponds with the user. This happens transparently. Password should be user-supplied with the option to change it. We only store the relation between user and issued client-ids, no passwords.
We have to create a custom grant, which works similar to client credentials, but also checks if the corresponding user is active etc. (which I think should be possible by injecting UserManager)
Resulting access token lifetime is short, interaction with our APIs is expected to be short-lived.
Assuming it is safe and easy enough to write such a grant, we should be able to cover everything we need.
Of course, I might have completely overlooked something :)

Scope and Claims (again!)

I'd like to ask a question to confirm my understanding of how to use Scopes and Claims (roles). Let's say I have a User (User A with read only rights i.e. suitable read only role), a Windows Service (Client A with read only access), an MVC site (Client B with full access), and a Web API. I want the Web API to be accessed by Users and Clients with full access and read only access.
I create two Scopes "sampleApi.full and "sampleApi.read_only"
I create two Roles "full_access" and "read_only"
I configure the Web API with RequiredScopes = new[]{"sampleApi.full", "sampleApi.read_only"}
When Client A connects to the Web API, it passes an Access Token containing Scope "sampleApi.read_only" and I can use [ScopeAuthorize("sampleApi.full)] or ScopeAuthorize("sampleApi.full, sampleApi.read_only")] on my Classes and Methods to fine tune accessibility. No problem.
However, when User A logs in, then he/she "inherits" the Scopes of Client B. So the Access Token contains "sampleApi.full", "sampleApi.read_only", and Role "read_only".
Now I have a problem at the WebApi in that I need to act differently when being called by a User. In that case I ignore the Scopes and use his/her Roles and the User gets "read_only" access which is what I want.
That being correct, it no longer makes sense to use the ScopeAuthorize attribute, and I need a custom hybrid attribute that does something along the lines:
If Caller is a User
- then use Roles to determine accessibility
Else
- use Scopes to determine accessibility
or have I completely misunderstood?
Scopes model what a client (not user) is allowed to access. They are manifest as claims in the token. The user's claims are also in the token. Authorization in the resource will be based on a combination of what the client is allowed to do and what the user is allowed to do. That's it.

How to link different authentication providers in azure mobile services

What is the best practice in azure mobile services to use different authentication providers (Facebook, Google, Windows e.t.c.) and understand that this three logins belong to the same user.
Out of the box if a user1 choose to use Facebook for authentication on his mobile phone and add some information to the app, and later he (user1) try to login with Google on his tablet, he will not see his information. Because they are two different users with different tokens. And I want to take some additional information from authentication providers (email) and has my own user table which contains email and other profile info shared for user no matter what provider he uses. How could I achieve it?
P.S. I use .NET as a backend and Windows Phone as a client
There isn't an out-of-the-box solution here. You would probably be best served by using a lookup table which maps a static user ID that you define to different identity provider IDs. Then, everywhere that you take a dependency on the user ID, you would do a lookup to match the current user identity to your static identifier. Your user ID is what gets stored everywhere else in the database.
The important detail here is that a Mobile Services token maps to a single provider identity. If you look at the user ID, it is actually provider:providerID. So we need to obtain two tokens and validate both together in order to associate two IDs.
On the client, you would have to manually prompt the user to link accounts. You would stash the current token in memory during this process, log in with the new provider, then call and API on the backend which does the association.
string existingToken = App.MobileService.CurrentUser.MobileServiceAuthenticationToken;
App.MobileService.Logout(); // allows login with new provider
await App.MobileService.LoginAsync("google");
await App.MobileService.InvokeApiAsync("associateToken", existingToken);
On the server, you need to be able to validate existingToken (the new one being implicitly validated by restricting the API to AuthorizationLevel.User)
Within that API, you can validate the token using:
IServiceTokenHandler handler = this.Request.GetConfiguration().DependencyResolver.GetServiceTokenHandler()
ClaimsPrincipal claimsPrincipal;
bool didValidate = handler.TryValidateLoginToken(existingToken, ConfigurationManager.AppSettings["MS_MasterKey"], claimsPrincipal);
You should probably also look up the user ID in your lookup table to avoid conflicts.
So overall that's a rough sketch of a possible solution. Unfortunately there isn't anything more turnkey.

SAML assertion with username/password - what do the messages really look like?

I need to create a some SAML 2.0 assertions, and I'm having trouble finding what the XML should really look like. Most of the documentation seems to be about using particular tools, not about the messages. I've got the schemas, with a plethora of possibilities, but I can't find an example of what the relevant messages actually look like in practice.
The business rule says: in order to create a shared identity, the user tells system A their username and password on system B. System A needs to communicate this info (along with some demographics) to system B. System B validates the information and passes back a unique identifier which can then be used to refer to this user.
Could someone give me an example of what SAML 2.0 assertions would look like to carry this information?
FWIW, I'm using C#, and need to pass the XML around in ways which preclude using a 3rd-party tool.
I'm not sure your use case is quite what SAML 2.0 does.
What you describe as your business rules actually looks like a use case for identity provisioning, not access management.
Standard SAML 2.0 use cases focus on one party asserting identity (the identity provider) and the other party (or parties) relying on those assertions (the service provider). Assertions carry what's called a name identifier, use of which is agreed ahead of time between the identity provider and the service provider.
These name identifiers can be pretty much anything, but they broadly fall into two categories: transient and persistent. A transient name identifier is only useful in the context of the current session (and essentially only says, "I know who this person is") and tends to be used to protect the identity of the principal while allowing privileged access of some type. A persistent identifier can either be opaque (in a similar way to how OpenID is used to access SO) where the asserting party can repeatedly verify a principle's identity without disclosing their identity while maintaining a dynamic but stable shared identifier between the asserting and relying parties or more substantial, such as an Active Directory UPN (which can be pre-agreed ahead of time).
When it comes to passwords, as you mention in your question, the service provider (relying party) never sees the users password. The service provider hands the user over to the identity provider with an authentication request. The identity provider sends the user back to the service provider with a response, which in the case of successful authentication contains an assertion about the identity of the user in the context of the relationship between the identity provider and the service provider.
In context of your question, the big thing is that SAML 2.0 does not provide a way to either create the local "application" user account or link that local user account to a federated identity. This is simply not the problem SAML 2.0 tries to solve.
Now, back to your business rules...
It looks to me like what you're trying to do is either account linking or registration - I would approach it like this:
User visits application, clicks a button to use identity from the identity provider
The application produces an authentication request and directs the user to the identity provider, carrying that authentication request
The identity provider either logs in the user or reuses an existing identity session if the user has one. The IdP produces a response message containing an assertion about the user. In your case this assertion should at minimum carry a persistent name identifier. The identity provider directs the user back to the application, carrying the response message.
The application processes the response message. If a mapping entry exists for the persistent identifier passed the user is recognised from that mapping and logged in as that local application user. If no mapping entry exists the user can be asked to locally log in, and on successful local login the mapping entry can be produced, or a user account could be automatically created and the user could be asked to enter additional information (names, email addresses, etc.) The "corporate" use case would be that no automatic account linking or creation is allowed and that the mapping must exist ahead of time.
As for the content of the messages...
The OASIS Security Services Technical Committee has a zip file download available with extensive documentation of the parts of the XML schema, including examples. It's also well worthwhile reading the protocol and profile documentation, as these describe the flow of messages between the parties involved in the identity conversation.
There are a large number of presentations floating around that I found very useful. Specifically, SAML v2.0 Basics by Eve Maler helped me start realising what problems SAML v2.0 was trying to solve. This presentation includes examples of that assertions look like. There is an updated presentation and links to additional resources on saml.xml.org.
I'm not sure if any of this is going to help though, as your use case does not seem to be what SAML 2.0 is trying to do. You can add attributes and extensions as needed to requests and responses, but I can't see many identity providers doing anything with those attributes and responses.