I'm integrating Azure Active Directory into a cloud platform. As our application is multi-tenant and relies on platform-specific claims, we've identified the simplest way to go about this is get an Azure AD token via our SPA, pass it back to our WebApi, validate it and return to the SPA a platform token with all the claims we need to go about our normal business (as if it was a simple username/password athentication request).
I'm concerned at the level of security for this though.
Some Context
As our platform is multi-tenant, we request that clients each register the application on their Azure AD portal, then supply us with the generated Application (client ID) and Directory (tenant) ID. We use these two pieces of information to make the initial request to Azure via our front-end SPA (following the node.js example provided by Microsoft's Quickstart guide when registering an app). Now because the user is unauthenticated at this point, we needed some way to return those two specific ids for the client. We have accomplished this using a sub-domain for identification.
E.g. acmeinc.mydomain.com will return a different Application (client ID) and Directory (tenant) ID than billy.mydomain.com. These are obviously public now as this request happens from an un-authenticated front-end route.
I can handle the token response just fine, both in the front-end and in the back-end when I pass it along, and validate that these two pieces of information are correct in the token, but seeing as the front-end is given them to begin with, validation on these is redundant. Also, validating the issuer seems equally redundant as someone who knows the Directory (tenant) ID, can fake that too (right?)
Am I missing something here? I would feel far more at ease if it were possible to request the client also include a claim that my platform generates privately such that I could validate this claim alongside the normal JWT validation. Custom claims do not seem possible from the Azure AD Portal.
Am I missing a critical step, or just overthinking this?
Someone cannot fake the issuer in the token because the token is digitally signed.
Without the private keys of Azure AD, it isn't feasible to generate a valid signature.
Without that, any modifications to the token will be immediately noticed because the signature does not match.
Your back-end should already be validating this signature if you are using standard JWT validation.
Requiring customers to register an app in their tenant is a bit of work that I would prefer not to put on them.
Have you considered making your app a multi-tenant app in Azure AD?
That way your customers could login to your app, consent to the permissions required, and start using it. Without needing to manually register anything.
This could be done in an on-boarding flow where the user signs in, and then they can decide what sub-domain they want.
You will at that point know their tenant id, which you can store. So in the future you can always use the correct tenant/directory id when signing them in.
The downside of this approach is managing the reply URLs.
With the specially registered apps, they can register their own sub-domain version as a reply URL.
With this generic multi-tenant app, you'll need to manage them.
And you can't add an infinite amount of them, and wildcards aren't supported anymore either.
So, your authentication would have to happen with a generic authentication reply URL like auth.mydomain.com, from which they would be redirected to their tenant URL.
Related
I want to authenticate users with Azure Active Directory (AD) in a mobile app that calls its own REST API and possibly, make it simple.
Looks like the documented way (here or here) to do so is to
register the API app with AD, expose some scope(s) as delegated permissions
register the mobile app, add these scopes as API permissions to this app
do authorization decisions in the API app based on these scopes
Question:
Now, since I feel the front-end and back-end parts of my app should belong into the same "black box" plus there are no fine-granular user roles within the app that would justify usage of multiple scopes or require the user to consent to using them, I'm wondering whether there is a recommended (and secure) way to go with just one app registration instead of two?
What I tried:
When using Okta in a similar scenario, I only had one app (clientId) and the back-end configuration pretty much validated the JWT token issuer, domain and a default audience string (in my understanding). I tried inspecting tokens from AD acquired via the authorization code flow for usual scopes (openid profile) to see what their audience was and if this could be reproduced - this is what I've got:
the well known GUID of Microsoft Graph (for the access token) - this one doesn't feel "correct" to validate, as pretty much any AD user could present an access token for MS Graph and only assigned users should be able to use my app
client ID of the app (for the ID token) - but the docs says these should not be used for authorization, so not sure if it's a great idea to pass them as Bearer tokens to the API
The standard thing in OAuth technologies is to only register a client for your mobile app. Azure has some vendor specific behaviour when it comes to APIs, related to the resource indicators spec. When there is no API registration, your mobile app will receive JWT access tokens with a nonce field in the JWT header. These are intended to be sent to Graph, and will fail validation if you ever try to validate them in your own APIs.
If like me you want to stay close to standards, one option is to add a single logical app registration, to represent your set of APIs. You might design an audience of api.mycompany.com, though Azure will give you a technical value like cb398b43-96e8-48e6-8e8e-b168d5816c0e. You can then expose scopes, and use them in client apps. This is fairly easy to manage. Some info in my blog post from a couple of years back might help clarify this.
Now, since I feel the front-end and back-end parts of my app should belong into the same "black box" plus there are no fine-granular user roles within the app that would justify usage of multiple scopes or require the user to consent to using them, I'm wondering whether there is a recommended (and secure) way to go with just one app registration instead of two?
You can create just one app registration; in fact the newer app registration model was designed to do that.
In the case where an API is used only by the app itself, I would register a single scope, something like MobileApp.Access.
Your API should verify the presence of this scope to prevent unauthorized applications from calling it.
In addition to verifying the scope, you will need to verify user permissions.
And filter the data based on their identity, depending on your use case.
Your question seems to suggest that you might be mixing scopes and user roles.
Scopes are permissions given to an application.
Also called delegated permissions; they allow an app to do some actions on behalf of the signed in user.
I'm using the auth endpoint https://login.microsoftonline.com/tenant-id/oauth2/v2.0/token programmatically (Nodejs) for getting back a token that will be used against my API. I have everything properly configured to send the request using a "Client secret" I setup on the Azure Portal - App registration service.
This issues a valid token that I can later check with the help of the Passport azure AD npm library. However I've been looking for a way of somehow adding more metadata to that token (i.e. a custom user name) so that when it gets validated and parsed by my server upon future requests I can extract this information.
When issuing tokens using a frontend application library (like msal) I have access to some of the user's information on the token (like its oid and email address). I'd like to be able to "extend" the token generated by the client secret to also contain a couple custom fields, which I can use after validating and parsing it.
Hopefully that's clear enough. I'm lost on how to achieve this. Thanks
It is a common requirement for APIs to authorize based on claims stored in the business data, eg roles or other custom data.
OPTION 1
Ideally the authorization server can reach out at the time of token issuance to an API or database to include the custom claims. This is not always supported though.
OPTION 2
Another option is for the API to process the incoming access token into a ClaimsPrincipal and to include custom values at that point. For an example see this code of mine.
PRIVACY
When adding more claims, you should also be careful about revealing sensitive data in JWTs returned to internet clients. Eg if you include names and emails, they are easily readable, and this can sometimes be a security concern.
My situation is this. I have a legacy Angular application which calls a Node API server. This Node server currently exposes a /login endpoint to which I pass a user/pwd from my Angular SPA. The Node server queries a local Active Directory instance (not ADFS) and if the user authenticates, it uses roles and privileges stored on the application database (not AD) to build a jwt containing this user's claims. The Angular application (there are actually 2) can then use the token contents to suppress menu options/views based on a user's permissions. On calling the API the right to use that endpoint is also evaluated against the passed in token.
We are now looking at moving our source of authentication to an oAuth2.0 provider such that customers can use their own ADFS or other identity provider. They will however need to retain control of authorization rules within my application itself, as administrators do not typically have access to Active Directory to maintain user rights therein.
I can't seem to find an OIDC pattern/workflow that addresses this use case. I was wondering if I could invoke the /authorize endpoint from my clients, but then pass the returned code into my existing Node server to invoke the /token endpoint. If that call was successful within Node then I thought I could keep building my custom JWT as I am now using a mix of information from my oAuth2 token/userinfo and the application database. I'm happy for my existing mechanisms to take care of token refreshes and revoking.
I think I'm making things harder by wanting to know my specific application claims within my client applications so that I can hide menu options. If it were just a case of protecting the API when called I'm guessing I could just do a lookup of permissions by sub every time a protected API was called.
I'm spooked that I can't find any posts of anyone doing anything similar. Am I missing the point of OIDC(to which I am very new!).
Thanks in advance...
Good question, because pretty much all real world authorization is based on domain specific claims, and this is often not explained well. The following notes describe the main behaviors to aim for, regardless of your provider. The Curity articles on scopes and claims provide further background on designing your authorization.
CONFIDENTIAL TOKENS
UIs can read claims from ID tokens, but should not read access tokens. Also, tokens returned to UIs should not contain sensitive data such as names, emails. There are two ways to keep tokens confidential:
The ID token should be a JWT with only a subject claim
The access token should be a JWT with only a subject claim, or should be an opaque token that is introspected
GETTING DOMAIN SPECIFIC CLAIMS IN UIs
How does a UI get the domain specific data it needs? The logical answer here is to send the access token to an API and get back one or both of these types of information:
Identity information from the token
Domain specific data that the API looks up
GETTING DOMAIN SPECIFIC CLAIMS IN APIs
How does an API get the domain specific data it needs from a JWT containing only a UUID subject claim? There are two options here:
The Authorization Server (AS) reaches out to domain specific data at the time of token issuance, to include custom claims in access tokens. The AS then stores the JWT and returns an opaque access token to the UI.
The API looks up domain specific claims when an access token is first received, and forms a Claims Principal consisting of both identity data and domain specific data. See my Node.js API code for an example.
MAPPING IDENTITY DATA TO BUSINESS DATA
At Curity we have a recent article on this topic that may also be useful to you for your migration. This will help you to design tokens and plan end-to-end flows so that the correct claims are made available to your APIs and UIs.
EXTERNAL IDENTITY PROVIDERS
These do not affect the architecture at all. Your UIs always redirect to the AS using OIDC, and the AS manages connections to the IDPs. The tokens issued to your applications are fully determined by the AS, regardless of whether the IDP used SAML etc.
You'll only get authentication from your OAuth provider. You'll have to manage authorization yourself. You won't be able to rely on OIDC in the SAML response or userinfo unless you can hook into the authentication process to inject the values you need. (AWS has a pre-token-gen hook that you can add custom claims to your SAML response.)
If I understand your current process correctly, you'll have to move the data you get from /userinfo to your application's database and provide a way for admins to manage those permissions.
I'm not sure this answer gives you enough information to figure out how to accomplish what you want. If you could let us know what frameworks and infrastructure you use, we might be able to point you to some specific tools that can help.
Background
I'm building a .NET MVC enterprise web application that must have the ability to authenticate users from different companies. One of the major requirements was to ensure that users don't need to create and remember new credentials to use the application, instead they should continue to use whatever credentials they use to access applications within their company intranet.
Since the application will be hosted on the extranet and needs to handle authenticating against multiple domains (i.e. multiple Active Directories), we are expecting each client to set up a security token service (AD FS) that the application can interface with to implement claims authentication.
The MVC application will check if the user is authenticated, and if not, start the workflow that ends with the MVC application being given a SAML claim being associated with the user.
Problem
At this point, the user is authenticated and given access to the MVC application. However, the application itself is a modern day web application that uses quite a bit of JavaScript to consume a .NET Web API that handles most of the business logic. My main question is how I can secure this API. I want to make sure the only requests being sent to this server are being sent from a valid source, and that the user consuming the service has permissions to do so.
Current Solutions
There are two approaches I can take to consume the API:
Straight from JavaScript (Preferred solution)
Route the request through the MVC server, which will then forward it to the API.
In order to pick an approach, I first need to find a way to secure the API.
HMAC Authentication
The most straight forward solution I've found is HMAC Authentication - http://bitoftech.net/2014/12/15/secure-asp-net-web-api-using-api-key-authentication-hmac-authentication/. However, this approach requires all API requests to come directly from the MVC server, since the secret key will need to sit on the MVC server.
OAuth 2.0
The second approach I can implement is some flavor of OAuth 2.0. The flavors I'm familiar with can be found here http://alexbilbie.com/guide-to-oauth-2-grants/:
Authorization Code
Implicit
Resource owner credentials
Client credentials
Authorization Code Grant
This is not the approach that I want to take. The MVC application has already received claims for the user - they shouldn't have to do it again just because the API needs the claim. (I have a followup question asking if I can simply pass the claim to the API server)
Implicit Grant
I like the way this approach sounds, since I will be able to execute API requests in the client (i.e. JavaScript code), however it suffers from the same problem as the first approach.
Resource Owner Credentials Grant
This approach is out of the question - I don't want either the MVC application or the API to ever hold onto the user's credentials.
Client Credentials Grant
This approach is the only reasonable OAuth approach listed - however I fail to see a major difference between this approach and HMAC authentication detailed above.
Questions
Have I correctly set up the MVC application's authentication structure? Specifically, in this context is it appropriate to have AD FS handle authentication and respond with SAML tokens representing user claims?
I plan to store user data in the server's session. Can I also store the user's claim in the session, and then somehow send that up to the API for authentication?
If I can pass the claim from the MVC server to the API server, and the API server can correctly authenticate the request, is it safe to pass the claim to the client (browser / JS code) so that consuming the API can bypass the MVC server?
Is the HMAC Authentication approach the best way to go?
Yes, using ADFS or any IdP products as an IdP for your application is a good way to implement SSO. Doing this way help you delegate all the federated access management as well as claim rules to ADFS.
Yes, you can store claims in session and somehow send them to the WebAPI. Please note that if you are using WIF, it already stores claims in Thread.CurrentPrincipal as a ClaimsPrincipal object. Another thing is that I assume you only want to somehow send the claims only, not the whole SAML2 token.
I would say it is as safe as the mechanism you use to protect the token on the client side. Check https://auth0.com/blog/ten-things-you-should-know-about-tokens-and-cookies/ and https://security.stackexchange.com/questions/80727/best-place-to-store-authentication-tokens-client-side for more details.
I can't say if it is best for you, but it seems to be a viable way, given that you have control over the WebAPI too. However, it also seems that using JWT token would be easier: https://vosseburchttechblog.azurewebsites.net/index.php/2015/09/19/generating-and-consuming-json-web-tokens-with-net/. Talking about JWT token, you can also ask ADFS to issue it for you: https://blogs.technet.microsoft.com/maheshu/2015/05/26/json-web-token-jwt-support-in-adfs/.
I'm trying to understand conceptually and practically how to perform an oauth2 with openID-connect flow in my web-api application, utilising Azure AD.
Importantly, when a request is made to the API I want to know who made the request.
My current understanding is :-
My client would detect that the user isn't logged in and redirect to a sign-in.
The user would provide their credentials, and be redirected back to the client, along with an oauth2 token.
This token would be supplied to web-api endpoints for any requests.
This is where it gets murky for me.
How exactly do I use this token to authorize access to a particular resource, determine who is accessing the resource, and what is the mechanism that does so?
I'm sort of assuming that I would need to reuse the token to make a call to the Azure AD user endpoint - if the token was indeed valid, the AD endpoint would return the users details - thereby providing some means of determining that the token is valid and providing details on the users identity. Authorizing access to a resource could be done through membership of groups in Azure AD.
BUT ...
I can only assume this a solved problem, and have noticed use of OWIN middleware as per this example
https://github.com/AzureADSamples/WebApp-WebAPI-OpenIDConnect-DotNet
But I'm still rather unsure as to what is exactly going on.
The service makes mention of scopes and claims, but I don't understand where these are derived from (I assume from a token supplied by the client, but not sure). The service must be receiving identity information in the call.
Which brings me to two points, for this to be secure -
The token provided in call to the service would need to be secured in transmission (hence the use of HTTPS) - to prevent MITM.
The token would need to be signed some how - I guess by using client secret or something - to prevent information in the token being spoofed.
Can someone help me clear up this muddled mess?
In particular -
How is the identity of the API caller determined - is identity determined from a call in the client or the server?
How to limit access to some endpoints of the API based on a user role?
What do I do to practically achieve this by building on existing middleware and libraries available to me?
Disclaimer: This will not be a comprehensive answer. It is off the top of my head.
OpenID Connect provides an identity layer on top of OAuth. In your case, Active Directory provides the authentication and sends back an access_token. The access token represents a user that AD has authenticated. If your doing OpenID Connect, then AD will also send an id_token, which may contain additional identity information (such as birthday, avatar, and whatever else AD exposes.)
Neither OpenID Connect nor Active Directory have anything to do with the the roles that your app assigns to a user; roles are entirely the bailiwick of your app. You assign user roles just like you normally would; you assign them to the nameid though instead of to an email address or username. Your app no longer has to authenticate the user but it does need to assign roles to the nameid.
How is the identity of the API caller determined - is identity determined from a call in the client or the server?
The identity is embedded in the access_token that AD includes in its response. This token will have a nameid in it that your app can associate with a user and role. The nameid is like an email address, username, or other uniqueID that your app uses to recognize the user.
How to limit access to some endpoints of the API based on a user role?
You choose. When your app receives a request with a particular access_token, that token will be associated with a particular user via its nameid, and you can assign whatever roles and rights to that user. Basically, associate roles with a nameid.
What do I do to practically achieve this by building on existing middleware and libraries available to me?
There is an unfinished demo here, though it doesn't use Active Directory as the provider, instead, it uses an internal provider. For the demo, the username is shaun and password is Testing123!. The source code is here.
Here is the link to the source of another demo, though again, it doesn't use Active Directory as the provider, instead, it uses Twitter.
The nice thing about OAuth and OpenID Connect is that we can use whatever identity provider we want, so you can adapt the demos to use Active Directory.
Apart from question #1 (the identity is verified on the service side) all your question are very open ended and would require a super long answer.
I would recommend reading https://azure.microsoft.com/en-us/documentation/articles/active-directory-authentication-scenarios/ - it is a good introduction to the flows underlying many of the modern authentication cenarios, including the web API one you are focusing on.
Once you have read that, you will find a complete set of samples in https://azure.microsoft.com/en-us/documentation/articles/active-directory-code-samples/ - in particular, I suggest studying the web API and thru authorization one to find guidance on the 3 questions you listed. HTH!