Multiple oauth clients for the same api - node.js

I'm trying to accomplish the following scenario.
I have and API at the moment and one web app. I have also create a new oauth client on my auth server (keycloak), which follows the implicit grant. I also used jwks on my nodejs api to do the token verification.
Now I want to create an SDK that will target the same API.
The questions is how do I get the SDK to retrieve an access token from the auth server. The first thought is that I will have to create a new client oauth client on the authserver and then use the client credential flow to get the access token. However, I dont know what should the behaviour of my API be like. At the moment it used jwks against a single audience. How should it be configured to verify access tokens from multiple clients (potentially thousand of them)

If you want multiple clients to call your API they should all use the same audience, and your first level of security will work.
The audience in access tokens represents the API(s) the token can be used against.
You will then need to use something else to authorize API requests, depending on the type of client and what they are allowed to do.
Configure each type of client in your auth server so that you are in control and know who is calling the API.
You may have 1000 clients but only 4 levels of privilege - in which case only configuring 4 OAuth clients may make sense.
One OAuth option you can use is give different clients different scopes. Scopes can represent high level privileges.
If a particular client calls an addOrder operation but does not have an Orders scope you could return a 403 response.
Often though API authorization needs to go beyond OAuth checks and apply custom rules based on the end user privileges.
If you can provide more info on your scenario I could provide a more complete answer.

Related

OAuth clarification

I've followed a training in Go as an introduction to microservices architecture a while ago. Getting back to this project I realise that I need more context as we've been quickly digging into the details of the implementations at the time...
I've drawn a simplified sequence diagram of 2 simple use cases:
The user logs in
The user is already logged in and make a purchase
(you can comment / modify the diagram at your convenience)
https://drive.google.com/file/d/1gWgkhJipUvWrVidkl7YFt_xlDmZYn_CX/view?usp=sharing
Here are the questions I have:
Here we're dealing with user authentication but what about client authentication? In the case of a web front end client, can I imagine storing an api_key and an api_secret in the env variables for the server that will be hosting this client? Because there use cases where the user is not logged but some services still needs to be available, but at the same time I only want my known clients (the web front and the mobile app) to be able to access those services (putting aside API Gateway solutions, and maybe other API Shields which would probably add another security layer against DOS etc.)
If the client logs in using Google/Facebook, the front app will receive an id_token that needs to be passed to the backend which would then verify the token ( https://developers.google.com/identity/sign-in/web/backend-auth ). In this particular case my OAuth API would not be used. Could please you confirm that it's the way it should be handled?
Many thanks.
EDIT 02/05/2022
Intro / Context
First thing first, Authorization is not Authentication.
Authentication is the process of verifying who a user is,
while authorization is the process of verifying what they have access to.
And like #Max said, OAuth is designed to manage Authorization and Open ID Connect (OIDC) is an extension of OAuth to manage Authentication on top of it.
The diagram I've exposed in my question is known in the OAuth world as the password grant, and, from the official documentation :
Because the client application has to collect the user's password and
send it to the authorization server, it is not recommended that this
grant be used at all anymore.
Authorization of my App (to get access to my APIs)
From the API perspective, we just want to ensure that the incoming requests are coming from the server that is hosting the App. So, in my case, it's simple machine-2-machine communication from backend server to backend server and there's no action required from the user. So, I must implement the Client Credentials Flow
...which would lead me to this flow:
https://drive.google.com/file/d/1qE9JpWRSRPa8z5iNxm7ocGkeT0E149Sv/view?usp=sharing (Feel free to comment / rectify )
Authentication of a user
Because OAuth knows nothing about authentication, I need an OIDC flow. The easiest one is based on the Authorization Code Flow with PKCE from OAuth below (only about authorization) ...
... but the difference is that we're passing an additional scope named openid in the authentication request (step 3), when the app performs the 2nd request to the token endpoint (step 7), the auth server returns an ID Token (which is a JWT containing user info in the payload -> authentication) in addition to the access_token (which do not contain user info but just "random string"). There's other OIDC flows with their pros & cons depending on the situation but it's another topic on its own (https://openid.net/specs/openid-connect-core-1_0.html)
User already identified by Google/Facebook
In case the client logs in using Google, the front app will receive an id_token. This token could be sent to the app server which would then make a request to the API Gateway, which then call the Auth api which would be in charge of verifying the token by calling the 3rd party auth server ( https://developers.google.com/identity/sign-in/web/backend-auth ).
In case of Facebook, we get back an access token, so I don't know how to deal with it ...
https://developers.facebook.com/docs/facebook-login/web
https://developers.facebook.com/docs/facebook-login/guides/advanced/manual-flow
Using Firebase, there's an onAuthStateChanged callback, so from the App perspective it will prevent request without the user being logged in, but from the API perspective, it doesn't guaranty that a request is coming from a logged in user...
https://firebase.google.com/docs/auth/web/manage-users#get_the_currently_signed-in_user
Warning: the answer below is not complete, it only serves to give a rough idea
Intro
OAuth2 is a protocol for authorization.
Grant Types
Over the OAuth2 protocol, you can use one of the "grant types" or "flow", one of these flows is illustrated in the picture you post and named password grant.
Each of these flows is realized for different scenarios, you rightly point the attention to how securely store the password on a web app.
For example for a front-end authentication (javascript / wasm) you can use a PKCE Flow where the secret_id is not used.
Endpoints
On OAuth2 there are two primary enpoints
Authorize endpoint - where you obtain the authorization code
Token endpoint - where you exchange the authorization code for the token(s)
Tokens
There are two types of tokens on OAuth2
Access Token
Refresh Token
The definition of token on OAuth2 is "an opaque string", you don't need to read it.
The access token is used against the API, this token has an expiration date, when it is expired the system use the refresh token to get another access_token whitout user interaction, when the refresh_token expire the user must re-authenticate again.
You can read the content of the access_token (which is a JWT token) from the JWT.io
Scopes
The Access token has, on its body, the scopes (i.e. Read email, read name, etc).
Scope is a mechanism in OAuth 2.0 to limit an application's access to a user's account.
Identity
On top of the OAuth2 are build other protocols OIDC aka IdToken aka Open Id Connect is one of them, in other terms OIDC protocol use the OAuth2 for establish an Authentication.
With the OIDC there is another token the id_token, this token came with the user's info and is NOT used has Authorizization in front the API.
There are also OIDC flows you can use to get the id_token and/or the access_token.
Conclusion
I suggest you read about OAuth2 from the references below and try different flows using the playground
References
Which oauth2 flow should I use
OAuth2
PKCE in more depth
My advice is to start with the data, which is the deeper area of OAuth.
USE AN AUTHORIZATION SERVER
This will enable you to keep your code simple. It will also handle Google / Facebook and many other forms of authentication for you, with zero impact on your code. The Curity Community Edition is a free and developer friendly option, though there are others. eg Keycloak, Ory Hydra.
PROTECT DATA
OAuth primarily gives you modern ways to protect data. Use scopes and claims to protect data across multiple microservices in a zero trust manner while securely maintaining user context. You will also need to manage joining identity and business data.
IMPLEMENT UI FLOWS CORRECTLY
Mobile apps use the AppAuth pattern. The current best practice for browser based apps is a Backend for Frontend approach. Both of these are tricky.
KEEP CODE STANDARDS BASED
All of the above Curity resources are based on OAuth related standards. If followed your apps will stay simple, with portable code, that can also work with other providers.
OAuth is very architectural though, and the best designs take time to learn, but you can learn the intricacies gradually. Our IAM Primer is a good starting point.

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

How to create JWT when a Client needs token for accessing multiple Audience?

I have created AuthorizationServer using OWIN/Katana OAuth 2.0 Authorization Server. It is configured to use JWT as the AccessTokenFormat. The SigningCredentials here are derived from Audience Secret that is unique to each Audience.
I want to build a Client that uses this AuthorizationServer to get a token for using an couple of API's I've built (resource / audience).
I see in OAuth there is no concept of Audience (JWT concept), the only thing closest to this is a Scope. I can pass multiple scopes (audience) from Client but I don't understand how can I create a JWT in this case since multiple Audience are required to be able to validate the resulting token.
Any help or guidance appreciated.
You should be careful not to confuse two different concepts. The Audience claim indicates for who the access token is intended. You can only use it for services that have that value configured in the allowed audiences.
Scopes limit what the client can do with the token on the service. For example, one scope may allow the client to post to your feed, while another scope gives it access to your list of followers.
So you would typically need two different tokens to access two different APIs. That does not mean the user needs to authenticate twice though.
The authentication happens on the authorization server and while the user is still logged in to that server, he/she won't be prompted for credentials again. The user will be prompted for consent the first time they try to access a new API.

Secure data access to RESTful API

I figured this has been answered before, but a quick SO search didn't yield anything.
I have a private API that is locked down by an APIKey. This key needs to be passed for each request. With this key you can access any part of the API. Obviously that's pretty open. For the most part this is acceptable. However, there are cases where I want to ensure that the request is sent by the owner of the data.
For example, consider an update or delete request. You shouldn't be able to make this request for someone else's data. So in addition to the APIKey, I'd like to have something else to ensure that this user making the request is authorized to perform that action.
I could require that an ownerID be passed with such request. But that's quickly forged. So what have I gained.
I am interested to hear what other members of SO have implemented in these situations. Individual APIKeys? Dual-authorization?
If it matters, my API follows the REST architecture and is developed with PHP/Apache.
API keys should be unique per user. This will verify the user and that they should have access to the data.
If you want to be even more secure you can have that api secret be used as a refresh token that can be used to retrieve an access token with an automated expiration.
SSL for all requests is also suggested.
Each API user has a unique API key. This key identifies them as a single user of the system. When dealing with more sensitive data, I've used client side certificates for auth, however Basic Auth + requiring SSL is usually sufficient.
When the request comes in, map the API key to the user and then determine if that user "owns" the resource they are trying to interact with.
The whole "determine the owner" part is a separate issue that can be tricky to do nicely in an API depending on how well the system was built. I can share how we've done that in the past as well, but figured that's a bit off topic.
Suggest you should consider using Oauth. In summary this is how it should work.
Each application making the API calls will need the respective application level APIkey for authorization through the Oauth process. Apikey here would just represent the application (client) identity.
Each end-user associated with the usage must authenticate themselves separately (independent of the apikey) during the Oauth authorization process. The users identity, associated context such as scope of authorization is then encoded into a token called access token.
Once the application obtains this access token, all subsequent API calls to access resources should use the access token, until expiry.
On the API implementation side, the access token validation should reveal the end-user context (including the scope of access that is granted during the Oauth process) and hence the access/authorization to use a specific resource can be managed by the resource server.

Resources