we're providing an OAuth app accessing the Microsoft 365 services based on the Graph API.
Some customers want to allow access only within designated IP ranges.
When I tried to apply conditional access for IP control, however, I faced the following problem:
If the scopes don't include openid, conditional access doesn't apply at all.
Once an access token has been issued, the conditional access settings can no longer restrict the use of the token (for example, the token can be even outside the designated IP range).
Is there any solution for these?
IP address is not a factor in the token. Consider that your app requires both an access token as well as an incoming request that us from a specific IP range. You can reject the request for either reason.
Related
I'm looking for guidance and/or best practices in implementing step-up authentication. The generic scenario is as follows: user logs in to web app using some identity provider, user then goes to some specific area of web site which needs to be protected by additional MFA, for example OTP. All functionality for the website is via REST API, authenticating with JWT bearer token.
The best description of the flow I found is from Auth0 here. Basically, user acquires the access token with scope which is just enough to access APIs that do not require additional protection. When there is a need to access secure API the authorization handler on backend would check if the token has the scope indicating that the user has completed the additional MFA check, otherwise it's just HTTP 401.
Some sources, including the one from Auth0, suggest using amr claim as an indication of passed MFA check. That means that identity provider must be able to return this claim in response to access token request with acr_values parameter.
Now, the detail that is bugging me: should the frontend know in advance the list of API that might require MFA and request the elevated permissions beforehand, or should frontend treat the HTTP 401 response from backend as a signal to request elevated permissions and try again?
Should identity provider generate relatively additional short-lived token to access restricted APIs? Then, if frontend has 2 tokens it must definitely know which token to use with which API endpoint. Or maybe identity provider can re-issue the access token with normal lifespan but elevated permissions? Sounds less secure then the first approach.
Finally, do I understand the whole process right or not? Is there some well documented and time-tested flow at all?
CLIENTS
Clients can be made aware of authentication strength via ID tokens. Note that a client should never read access tokens - ideally they should use an opaque / reference token format. Most commonly the acr claim from the ID token is used.
This can be a little ugly and a better option can sometimes be to ask the API, eg 'can I make a payment'? The client sends an access token and gets a JSON response tailored to what the UI needs. The API's job is to serve the client after all.
APIs
APIs receive JWT access tokens containing scopes and claims. Often this occurs after an API gateway swaps an opaque token for a JWT.
The usual technique is that some logic in the Authorization Server omits high privilege ones, eg a payment scope or claim, unless strong authentication was used.
It is worth mentioning plain old API error responses here. Requests with an insufficient scope typically return 403, though a useful JSON error code in an error object can be useful for giving the client a more precise reason.
STEP UP
As you indicate, this involves the client running a new code flow, with different scope / claims and potentially also with an acr_values parameter. The Curity MFA Approaches article has some notes on this.
It should not be overused. The classic use case is for payments in banking scenarios. If the initial sign in / delegation used a password, the step up request might ask for a second factor, eg a PIN, but should not re-prompt for the password.
CLIENTS AND ACCESS TOKENS
It is awkward for a client to use multiple access tokens. If the original one had scope read then the stepped up one could use scope read write payment and completely replace the original one.
In this case you do not want the high privilege scope to hang around for long. This is yet another reason to use short lived access tokens (~ 15 minutes).
Interestingly also, different scopes the user has consented to can have different times to live, so that refreshed access tokens drop the payment scope.
ADVANCED EXAMPLE
Out of interest, here is an interesting but complicated article on payment workflows in Open Banking. A second OIDC redirect is used to get a payment scope after normal authentication but also to record consent in an audited manner. In a normal app this would be overkill however.
I'm using Microsoft Graph API to access data from my Azure AD, including adding and updating users.
Is there any way I can limit access to the Graph API based on the client's IP? So that requests originating from a specific IP or an IP range will be served, and the rest will be blocked?
As far as I understand, Graph API deployment https://graph.microsoft.com is a public API that is protected by Azure AD. As long as you have a valid access token you are able to call the API and do what the access token says you are allowed to do regardless of where you are. This means access restriction can only be done at Azure AD level during authorization.
If you apps are user interactive then you can try using Azure AD Conditional Access Location Condition.
For daemon apps that run on server-side, this case may not apply because they run behind your trusted networks in most cases.
We have some web services, and an OAuth2 server that protects access to them.
I want our outside clients to be able to use these web services in their mobile apps. But in some cases, they want to maintain their own login/password database, and not require the user to authenticate separately to our web services. In that case the client has identifiers for users on our side that correspond to their own users (we sync these up outside of the OAuth process).
So, assuming the users have already established a session on the client's side, I want to be able to give them some kind of access token that will grant them access to the corresponding user on our side, without prompting them for a separate password. How can I do this?
One approach would be to require the clients to set up a proxy to our web services, protected by their own session. Their mobile apps would send requests to the proxy server instead of our web services directly. Their server could use the client-credentials grant to get an access token, and add it to any incoming requests before proxying them to our server.
Is there a better way? This seems kind of difficult for clients to implement, and you'd have to verify somehow that the incoming requests aren't trying to access data for a different user.
Is there any grant that would allow the client's server to request an access token on behalf of an individual user, without the user's interaction? Then maybe the token could be returned to the app, and the app could use it to access our web services directly. With the client-credentials grant, the token gives access to all users, so it's not safe to return to an individual user's app.
Access to user's resource without user login or consent is anti-oauth(doesn't matter if it is 1.0a or 2.0). Hence there is no grant_type to support this directly.
Also the proposal of proxy, may not be a good idea for 2 reason.
Security: That proxy will open a gaping hole acoross your systems,
that knowning a user's email, an attack can get all the data from
your system.
Maintanebility: How would you keep track of authorization that the
client credentials token had access to a certain email across
system? This may create unnecessary checkpoints in your application(s).
Now, to here is a proposed solution which may work without changing much of your application
Please note it will be good idea to enable 2 way mutual auth or some form of additional security for verification.
Let me know if this doesn't solve the problem.
For a B2B REST API servicing Enterprise clients who may have multiple applications using a Client ID/Secret:
If you send a request for an oAuth2 access token for a specific Client ID and Client Secret and receive an access token then later on send another request for a token with that same Client ID/Secret, should that invalidate the previous access token?
In other words, in this case, should a Client ID/Secret be able to request and use multiple valid access tokens? Are there different cases where this should be implemented or not?
OAuth2 is generally about a user delegating access to a client, so in the case where a client has many users (as it usually will), it will most definitely be using multiple access tokens since they will apply to different users.
Consider the situation where you grant access to your Google account to another online application (the client). Google issues an access token which might allow the client to read your contacts, for example, using Google's OAuth2 APIs (with your prior approval). Obviously it can only access your contacts with this token, not other people's. Google may issue many different access tokens to the same client, but each may correspond to a different user and/or resource.
The same authorization server may issue tokens for many different resources, so even in the case where there is no interaction with a user (as in the "client credentials" grant), a client may still need to manage multiple tokens.
Whether the authorization server invalidates a token when another is requested for the same user, audience, scope etc., would be implementation dependent. A client wouldn't usually need to do this and would normally use a refresh token to obtain a new token when its existing one was about to expire. I'd say it's generally more important that a user can invalidate existing tokens they have authorized, and that tokens can be invalidated for a particular client. Of course, this also requires that the resource server has some way of checking for token revocation before granting access.
Yes, a client can have several access tokens. It's meaningful, we're actually using.
Consider that tokens may have different scopes, so a client may have a token with scope "res1" for a resource and a another token with scope "res2" for a different resource.
Another use case may be to request a refresh token with several scopes, e.g. "read write" and use it to get a "read" scoped access token to initialize a management GUI, then get a new access token for each write transaction.
You can argue whether it's good design/implementation or not but it's definitely technically possible and not forbidden by the standard.
I am using oauth to access different services provided by google.I am able to generate token per service basis. But I want to generate single token to use multiple services from google.
Can anyone tell me the solution for this?
https://developers.google.com/accounts/docs/OAuth2
As per the Google OAuth2 docs, it is possible to do this by setting multiple scopes, but be warned, it isn't a happy experience.
When making your request, set the scope parameter to multiple scopes, each separated by a single space.
Example: "https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email https://www.google.com/m8/feeds"
You can currently find a list of scopes here: https://developers.google.com/gdata/faq
Unfortunately, API access is not additive, meaning, if you ask for an access token for the Google Contacts API, then later on as the same application ask for an access token for the Google Profile API, you will end up with two access tokens, and neither can be used to access the other API. Facebook at least has the decency to give you back a single access token that grants access to all the permissions granted so far.
Because of this, you are left having to keep track of multiple access tokens (a horrible nightmare, given they expire very quickly), or ask for all of your permissions up-front, which is a user experience disaster.
Fragmented and disparate, the Google APIs are currently setup to fail if you want to do tight, multi-faceted integration.