Single app registration in Azure for mobile app calling own backend - azure

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.

Related

Is it possible to utilise Open ID Connect flows for authentication but then have another source of authorization rules?

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.

AzureAD: Using long-lived refresh tokens for external API "system" consumers?

I'm developing a bunch of APIs that will have both internal and external (to the company) consumers. I'm using AzureAD for authentication. Whilst these consumers will be integrations written in code, I don't want to have to create and manage dedicated "app registrations" for each client/consumer. I also want to be able to use roles for more granular permissions.
It feels like a long-lived refresh token is the best option for this, and I've written a working proof-of-concept for this, which meets the requirements perfectly.
Given this is security though - I wanted to ask if I'm doing anything stupid or wrong.
First question - is it okay to treat a refresh token as a long-lived secret that consumers can store in their secure config, then their systems programmatically use that to query an access token to use against our APIs?
If this is okay - my second question is regarding the client id and secret. Because the implicit flow doesn't support refresh tokens, I'm using the authorisation code-flow. For this, it looks like I have to pass the client-id and client-secret as well as the authorisation code or refresh token to AzureAD. This means that I need to create a dedicated "auth api" that the consumers call to request these tokens. This auth api literally just then makes a downstream call to AzureAD passing the clientid and secret (which the consumer obviously doesn't know about). It feels like if the implicit flow supported refresh tokens I wouldn't have to implement this "auth API" at all. But because I have to use the authorisation code flow - it's forcing me to implement a proxy "auth api" for all token requests to go through. Am I missing something - or is this the way I should be doing it? It's fine if so - as this is what my PoC is doing, and it's working. But again, just wanted a sanity check on this with it being security related.
Ps. I know Azure API Management gives a lot of this functionality - but for reasons out of scope of this question, this isn't a good fit for us.
Update
To add another couple of reasons why this method fits my use-case really well...
A lot of internal developers will also be using these APIs (internal to the company). They already have AzureAd accounts anyway. So this then becomes super-simple to manage - we just have a bunch of security groups with certain roles in the app registration, and we can just add devs to those groups. And they don't need to know the client id / secret - they just use their own user account.
The APIs have Swagger UIs. Using users instead of clientid/secret - means developers can use the Swagger UIs with single sign on.
WEB CLIENTS
So a web app is used by developers to sign in via their Azure AD account. Authorization Code Flow is fine, after which each user will get access tokens and refresh tokens for calling APIs. Tokens will include the user's role and APIs can use them for authorization.
EXTERNAL API CLIENTS
These might be B2B clients and therefore use the Client Credentials Flow. Tokens issued to these clients would then have no user context.
INTERNAL API CLIENTS
It is a little unusual for a developer to login to a web client and then take tokens issued and use them in other apps. This is partly about reliability and partly because different apps generally access different areas of data. See this scopes article for details on designing how components call each other.
REFRESH TOKENS
A refresh token is something that will expire so you need a plan for this. Avoid using them in static configuration. Consumers need to handle refresh token expiry in order for their app to be reliable.
CODED INTEGRATIONS
Are these web clients or APIs, and how many distinct apps are there? It feels like combining these into one or a few client registrations is the right option. A common setup might work like this:
All developers might share the same registration
All web clients use the Authorization Code Flow - and you Auth API
API clients forward tokens to other APIs, to maintain user context

Azure Active Directory Token Validation

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.

Query users from different azure tenant

We have a case where we have 'clients'. Every client is an different Azure tenant but we keep their tenant id in the database. So we have Angular application where we want to have like a dropdown with all the clients and based on the selected client to query their tenant users so we can add him to our database and give them permissions and stuff to all other applications. As per my readings this in not achievable,
Because this permission application will be used from like 3-4 guys which are part of our tenant only.
Is there a way we can achieve that?
You would need to use the User.Read.All Application permissions and authenticate using the Client Credentials grant. You would then need to retrieve a token from each tenant prior to calling /v1.0/users.
Note that this will require receiving Admin Consent from each tenant you need to query.
Rohit's comment below is an excellent point. If your app is a SPA, meaning the authorization is happening entirely in the browser via Javascript, you're really limited to the OAuth's Implicit Grant.
To use Client Credentials or Authorization Code grants, you need some kind of backend API to handle the authentication and calls to authenticated APIs. I would argue that you should be doing this anyway, if for no other reason than forcing your user to reauthenticate every hour isn't a great user experience.
If you don't mind requiring each user in the tenant to authenticate, you could use the Authorization Code grant. This is a bit more complex of a set up because it requires you to keep track of separate Refresh Tokens for each user. Your backend would need to retrieve the Refresh Token, Exchange it for a set of new tokens (access_token and refresh_token), Store the new Refresh Token, and then call the API using the new Access Token.
Since there is a 1:1 relationship between the Token and the User so, at scale, you're looking at a lot of tokens. You'll also need a bunch of maintenance workflows to handle issues that may come up (refreshing the token fails, new scope requirements, etc.).
It really comes down to the depth of the relationship between your app and the tenant. If you're providing security and analysis to the entire organization, then asking for global Mail.Read is certainly reasonable. If you're providing a service to just part of an organization, it can be hard to get IT to sign off on such a broad permission scope.

Building a Web-API with Oauth2/OpenID connect

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!

Resources