OAuth authorization flow for private API with Microsoft AD - api

Our company is using Microsoft AD for user management and authentication, also the authorization is done using the AD groups/roles. In the most 3rd party applications the users can authenticate with their AD accounts.
Now we are developing new applications, which should use an internal API. Therefor we created a new enterprise app in our Microsoft tenant and defined a couple of roles.
On the client side it is the normal flow - users authenticate with their accounts and the client receives the access token it should send to the API. And here is the point where I am not sure what is the best way to implement it.
Since all the users already exist in the AD, there is no need to only use access token to get the user identifier and create/link the user in the internal database - I want to use the AD users and to be able to verify the roles and use them in the services behind the API gateway "as is". But the roles are not stored in the access token, so I assume, I have to request them from Microsoft separately. But also I do not want to request them every time a user sends a request to my API and want to rely on the token the cliends sends to me and which I can verify.
So what is the best way to implement it? Should I create a new Bearer JWT in our own auth service, containing all information I need, and provide it to the client, so that it sends it to me every time? Should client use this token for authorizing the user as well? But it also can request the IDToken from Microsoft? Would our internal token replace IDToken and Access Token? Or should we just use IDToken for requests to the API?
Creating an own token looks like an overhead to me, since we only work with AD users but I also don't want to use IDToken for authorization in the API.

In an OAuth architecture your apps (primarily APIs) accept tokens from the Authorization Server (Azure AD in your case). You then use these tokens to authorize requests for data based on Scopes and Claims. Avoid issuing your own tokens and use AS tokens consistently. It feels like you then need to deal with domain specific claims, which is tricky, and these are the main concerns:
Option 1: Custom Claims in JWT Access Tokens
This requires Azure AD to reach out to your internal API at the time of token issuance. This is the preferred option but it may not be supported - or possible - depending on the provider and hosting infrastructure.
Option 2: Custom Claims via Lookup
Here is some example C# code of mine that shows a technique where you form a custom claims principal in the target API. The extra claims are looked up (typically from a database) when the access token is first received, then cached for future requests with the same access token. It is not ideal but I have had to use it in the past due to vendor limitations.
Confidential Internet Tokens
Be careful when including claims in access tokens to not reveal sensitive data to internet clients, eg web or mobile apps. Aim to use the phantom token pattern if possible, so that you do not reveal any sensitive data. If the Authorization Server does not support issuing reference tokens, then option 2 above may be the least bad option.

Related

What's the proper way to implement a "static" authorization token feature using OIDC (or OAuth2)

I am exploring possible solutions for creating something like "API Keys" to consume my API. The goal is to allow for users to generate one or many "API Keys" from the web app and use the static generated key from the CLI app.
The web app and the client app are already using standard OIDC with JWT tokens for authentication and authorization using RBAC (role-based access control). The CLI app can already authenticate the user through the standard browser flow (redirects the user to the browser to authenticate and exchange the token back to the client).
The "API Keys" solution I am trying to achieve should have some fine-grained options where it won't authenticate as the user, but will authorize the client on behalf of the user (something like the GitHub Personal Access Token).
To me it seems like a "solved problem" as multiple services provide this kind of feature and my goal is to do it the most standard way possible using the Oauth2/OIDC protocols but I can't find details on what parts of the protocols should be used.
Can anybody provide any guidance on how it is supposed to be done using the Oauth2/OIDC entities?
Can I achieve it by only using Role-based access control or do I need Resource-based access control?
It went through the path of creating a new client for each "API Key" created, but it didn't feel right to create so many clients in the realm.
Any guidance or links to any materials are appreciated.
Can anybody provide any guidance on how it is supposed to be done
using the Oauth2/OIDC entities?
OIDC is based on OAUth 2.0 so after user login you have id tokens, access token and refresh token on the backend side. To generate new access token without asking user for authentication data you should use refresh token: https://oauth.net/2/refresh-tokens/
Can I achieve it by only using Role-based access control or do I need
Resource-based access control?
resource-based access control is more flexible solution here, but if you business requirement is not complex, then role based might be enough.
It went through the path of creating a new client for each "API Key"
created, but it didn't feel right to create so many clients in the
realm.
It is one application so you should use one client with specific configuration for access token and roles/permissions for users.
Update:
We can use GitHub as an example:
User is authenticated during login
for OIDC code is exchanged for id token, access token and refresh token
session for user is set for web browser
User can request access token
in GitHub authenticated user can request github.com/settings/personal-access-tokens/new endpoint
request is accepted, because user is authenticated based on session
backend service responsible for returning access token can obtain new access token using refresh token from point 1.
access token is returned to GitHub user
To call your API in an OAuth way, CLI users must authenticate periodically. Resulting access tokens can be long lived, as for GitHub keys, if you judge that secure enough. The access token returned can be used exactly like an API key. There may be a little friction here between usability and security.
CONSOLE FLOW
The classic flow for a console app is to use the Native Apps Desktop Flow from RFC8252. This involves the user interactively signing in using the code flow, then receiving the response on a loopback URL. It is an interactive experience, but should only be required occasionally, as for GitHub tokens.
API KEYS
The access token returned is sent in the authorization header and you can use it as an API key. Access tokens can use a reference token format. to make them shorter and confidential, to prevent information disclosure. These will be more natural in a CLI.
API AUTHORIZATION
When your API is called, it must receive access tokens containing scopes and claims, to identify the user. This will enable you to authorize correctly and lock down permissions.
{
sub: 586368,
scope: repos_write,
topic: mobile,
subscription_level: silver
exp: ?
}
TOKEN REFRESH
Sometimes CLI access tokens are long lived, for convenience. A more secure option is for the CLI to use token refresh. It can then store a refresh token in OS secure storage, then renew access tokens seamlessly. My blog post has some screenshots on how this looks, and a desktop app that does not require login upon restart. The CLI needs to deal with expired access tokens and handle 401 responses.
DYNAMIC CLIENT REGISTRATION
Some developer portal scenarios use DCR. It is another option in your security toolbox. It could potentially enable a silent client per CLI user:
User runs a standard authentication flow with a DCR scope
This returns an access token that enables client registration
The resulting token is used to register a new client
This could potentially be a client ID and client secret used in a CLI
Afterwards, the user and client are bound together. Probably not immediately relevant, but worth knowing about.

Where to store tokens obtained through OAuth2 (OpenID Connect)

I build an application that uses some Identity Provider (Auth0, FusionAuth, Azure AD, AWS Cognito) on user's choice.
I'm using Authorization Code flow.
And i faced issue with storing tokens.
I want to use Identity Provider to only user's sign in, i do not need to store who is the user (name, email etc.). I just need to authenticate user and be sure that user come from Identity Provider that i can trust.
So i have 4 questions:
Do i need to store tokens if i am not consider to use them to make requests to the Identity Provider.
If no goto 4 question. If yes i want to know what the best way to store them (save in session with db or just send them as accessToken for Header and refreshToken in cookie)
How i can validate access token, because as i know access token may or may not be JWT. Make request to IP on each request is not the best way, because of amount of requests.
Should i use my own created pair of access and refresh tokens to validate requests from Front End.
I'm only recently started investigate OAuth2 and will appreciate any answers.
As of now i have this flow:
From Front End(FE) user redirects to the Identity Provider(IP) to sign in.
IP redirects to the Back End(BE) with code.
BE make request to IP to obtain tokens.
BE validates that authorization is valid (via nonce and state).
BE redirects user to the FE with refreshToken in the httpOnly secure cookie and accessToken in query to store it in localStorage.
When FE make request to BE i validate accessToken(JWT) using jwks.
In OAuth you should not generally have to implement plumbing to build your own token stores. Eg tokens can be stored in strongly encrypted HTTP only SameSite=strict cookies. However you have to stay within cookie size limits. The best way to do this is to issue opaque tokens (such as UUIDs) to internet clients. The Phantom Token Pattern has more info on this.
You should not use foreign access tokens in your own APIs. As you are discovering, you may not be able to validate them. Also they will not have meaningful scopes and claims and you will not be able to authorize API requests properly. Instead issue your own tokens for your own APIs.
AUTHORIZATION SERVER
It is possible to issue your own tokens in code but this is not recommended. Instead, the preferred option is to use an Authorization Server. One option is the free community edition of the Curity Identity Server.
This component will take care of connections to Identity Providers for you. It will then issue tokens for you, so that your apps and APIs only ever deal with tokens from a single provider.

Developing a RESTful API with OAuth and/or OpenID

Im struggling to wrap my head around implementing OAuth or OpenID with multiple external token providers. Since from my perspective the providers like google mix both specs in a single api, im differentiating these two mechanism in the way i protect my ressources and deal with user data. OpenID is only used for authentication and i produce my own access_tokens and persist all of the user data myself, while on the other hand OAuth provides external access_tokens and manages user data.
Entities involved:
External provider - which is my term for the OAuth/OpenID provider like Google OAuth
Backend - Server which serves primarily as a RESTful API for the clients
Clients - Apps (e.g SPA, IOS App, Desktop clients) which need to access ressources provided by the backend
Im developing an express backend (rest api) for several different sort of clients including web, ios/android. From my understanding i have the following options: (referring to most implementation docs of the provider i want to use instead of the spec)
Option 1 - OpenID
The client acquires an auth_code by signing in with any external provider (Apple, Google, Facebook)
The client sends this auth_code to my backend where this code is used to issue an id_token
The backend uses this id_token to authenticate the user and store any required information about the user
The backend generates an access/refresh token for authorization and sends these back to the client
Now i can use my access_token for authorization and the refresh token for auth-state-management (signout, invalidate tokens)
Problem - Is there a problem really ?
Im not sure if i need to frequently check if the user is still a valid identity. With valid identity i mean wether the external identity (e.g. google user) still exists, which basically relates to wether my persistance layer has to invalidate (delete) this user. In other words do i have to sync my persistance layer with the external provider to avoid dead/unusable identities. This is especially a problem if information like the email address changes and my backend does not get notified about that. Or should i just live with the fact that the user in my backend is just related to the external user by the id and the clients have to manage their data in my backend themselves (e.g change their email at the client). That would mean i preferable ignore any changes to the external user data (at the provider).
Option 2 - OAuth
The client acquires an auth_code by signing in with any external provider (SiwA (ios), Google, Facebook)
The client sends this auth_code to my backend where this code is used to issue an access_token/refresh_token from the provider
The backend sends back the access_token/refresh_token obtained from the external provider
Now everytime the client does make a request it has to contain the external access_token which then is used at the backend to ask the external provider if this token is valid and the client has access to the ressource. In other words i use the external access_token for authorization
Everytime user data (e.g. email, address...) is required at the backend, it is necessary to ask the external provider for this data by providing the access_token, which was given by the client
Problems/Questions:
I assume that the refresh process has to be perfomed on client side in case the backend redirects unauthorized from the provider in case the token expires. Is that correct ?
How do i determine from which provider the token is. It seems weird for me to implement a trial and error process and just ask every provider if this is a valid token. E.g. if the backend receives an access token in the header of the request it doesnt know which provider to ask. (or should i encode this information in the header like Bearer Provider Token in order to know where to check the access token.
Using Option 2, anytime the external provider experiences downtime no user is able to use my backend, while with using Option 1 only the signin (inital sigin or after explicity signing out, which invalidates the refresh token) is not availabe for this specific provider.
Is there anything i'm missing ? It seems to me that Option 2 introduces a lot of unnecessary communication to the auth provider, while Option 1 does neglect any communication which is potentially required (e.g. sync of identity state) ?
The main question for me is, considering Option 1 which seems more suitable for my scenario, do i necessarily have to react to any state change of the user state, like change of email at the external provider or are there any downside to ignoring anything then the external user id to allow for authentication.
I ended up implementing OpenID, realizing i only needed authentication and no authorization nor rigorous coupling of user data. At the time of asking the question, i was aware of the difference, however i didn't dig deep enough into the requirements of my project. Thus i discarded the basic OAuth protocol, since i didn't need any authorization to external ressources.
Regarding OpenID, the management of external identities from the OpenID provider is not in the scope of the protocol it has to be done independently. There are other protocols and methods dealing with that e.g. SCIM.
I ended up relying on the fact the the external id provided with id_token is unique and initialize a one time mapping at the first time authenticating (basically a signup). My server manages the user data from this moment on. Subsequent authentication request rely on the fact that this mapping never changes and any user data may differ compared to any data kept at the provider, e.g. different mail addresses at my server compared to the google mail of the external identityl. However this doesn't violate my requirements.
Furthermore, i want to add that i ended up supporting implicit flow and auth code flow, which means the client can send the id_token directly, instead of sending the auth_code. I did not fully get the point why this is more unsecure since from my current perspective my server ask the provider to verify the id_token which prevents any malicious intends by proividing false id_tokens.

Throttling & Quota by users - Token Management

I would like to implement quotas for users accessing my API but I'm not sure the flow I have in mind is the way to do by simply reading documentation from several API management solutions.
Currently, my flow could be described as follows :
The user provides credentials to the app
The app calls my Authorization Server for validation. The token is returned to the user if successful.
In the following requests, the app will validate the token (Authorization header) against the Authorization Server before accessing the service.
My problem is that I cannot implement quotas based on tokens since my users would be able to get a new token to avoid the limit. According to your experience, is it possible to manage quota by users at the gateway level or should I change my API authentication method?
Best regards,
When we speak of api and token the most used model of communication is the protocol OAuth 2.0.
Through it, API users must authenticate to their respective OAuth authentication server (it could be a third-party server, eg facebook or google).
With the token in hand and this token is a token with a limited lifetime, the exposed API must validate this token against the OAuth resource server which will identify who will be the client / application that is requesting.
Therefore, using OAuth token it will be possible to identify the requester.
Regarding quota control if you will not use any API Management / Gateway market player (Ex: apigee) you must implement this control with a high-performance query engine. For a simpler solution a key value pair database could solve this problem (eg redis).

restful api authentication confusion with oauth2

I did some investigation about restful api authentication. Most people pointed to Oauth2 for restful api authentication. I looked into some of resouces, especially this link https://developers.google.com/accounts/docs/OAuth2.
It seems to me Oauth2 is for a third party app to access users' data in google/facebook(or other data provider).
Our problem is that we own the data, we don't need to access our client's any third party data and our clients don't have to any third party data. We want to protect our api with some sort of authentication.
For our case what is the convenient technologies for our restful api authentication ? We will expose our api like this
https://ourdomain.com/api/<endpoint>
Our clients can access a website first to register https://ourdomain.com and they should be able to get clientId and clientKey from our website for accessing apis. Our clients should be able to consume through some sort of authentication
In oAuth 2.0, there are several types of grant types. A grant type is just a way to exchange some sort of credentials for an access token. Typically oAuth refers to 3rd party usage with a Authorization Code Grant. This means redirecting the user to the resource owner's website for authentication, which will return back an Authorization Code.
This clearly doesn't make sense for 1st party oAuth use, since you ARE the resource owner. oAuth 2.0 has considered this and included the Resource Owner Password Credentials Grant for this purpose. In this case, you can exchange a username and password for an access token at the first party level.
See https://www.rfc-editor.org/rfc/rfc6749#section-4.3 for more details.
If I understand correctly, what you need it similar to OAuth in a way that you do the exact same thing minus granting a 3rd party app access to a user's resources.
In OAuth, there is a central system that manages authentication and authorization by checking an app's credentials + user's credentials and dishing out authorization tokens. There are multiple endpoints that will accept these authorization tokens.
The tokens are basically encrypted strings that contain info about the user's credentials and some other info that might be needed by your app.
What you need (i believe) is a similar authentication endpoint, that the client hits with its credentials and gets a token.
So,
i) Create a registration form/console where a client can register and get his credentials. Have a look at this.
ii) Define a HTTP endpoint where the user exchanges his credentials for an access token + refresh token.
iii) The client can hit the resource endpoint with the access tokens to make authenticated calls to any of your endpoint.
iv) At the back-end you'd need a common service that verifies the tokens and extracts info from it.
PS - This is just a minimal system, there would be a lot of security considerations like what if some unauthorized app gets access to some client's access tokens.
You can find much information about CSRF attacks, noonces, timestamps and other methods of mitigating security concerns.
Just to be clear with the original question:
OAuth2 needs at least a client and a server
OP was wondering how to secure a REST API, and why everyone is talking about third party authentication providers (Google, Facebook, ...)
There are 2 different needs here:
1 - Being able to secure a personal API (ourdomain.com)
Client Server
Consumers <----> Your API
2 - Being able to consume a public API (For example getting a user's Google contact list)
Client Server
You <----> Google APIs
OP actually needs the 1st: implement an OAuth2 server in front of its own API.
There are many existing implementations for all languages/frameworks on Github
Finally, here is one nice Oauth2 technical explanation, and I'm shamelessly taking one of its schemas here:
No I'm not working at Google, I'm just taking Google as a public API supplier example.