I am trying to build mobile app using react-native backed by spring boot apis and in order to implement authentication and authorisation, i researched and found JWT is a way to go.
There are lots of implementation available for example https://medium.com/#maison.moa/using-jwt-json-web-tokens-to-authorize-users-and-protect-api-routes-3e04a1453c3e
I have few questions:
Most of the time you have to store JWT token on your local mobile cache to use this on subsequent requests. How safe is it to store the JWT tokens as it is.
Normally your create user is not JWT protected because without creating a user you can't generate any tokens. So it practically means you have exploit your user creation and it turns hacker can create any arbitrary users and generate the tokens and get access to system how to avoid that.
How to restrict token roles based on only the logged in user. can we bind mobile device id to generate the JWT tokens.?
Related
I am building an ASP.NET Core 6 Web API application for mobile clients (and maybe later SPA JS app). The application should have sign-in with Google option. I also want to add my own app's custom sign up and sign in options that would also be based on JWT authentication and not cookie.
I understand that for my custom sign in flow my app will generated JWT that will be sent to the client.
But I have few questions how that works when user signs-in with its Google account:
who's responsibility is to generate the JWT when user signs-in with its Google account? Is that responsibility of Google or mine application? I don't want Google to return JWT to the client in the cookie.
Then when client is authenticated with Google, and sends requests to my application, how can my application validate JWT token it gets?
When user signs in with Google for the first time, should I automatically register that user in my application (I am using Identity framework) by taking claim values (email) from the JWT? What is the general practice here?
I am trying to understand these processes and flows so sample code is not necessary (but I do welcome it).
Ad.1. Normally, in a larger system, you would have an authorization server (AS) that would handle user authentication and the issuance of tokens. Your clients would contact only the AS, and the AS will be able to provide the user with different forms of authentication: e.g., through your website's password or through Google. The AS is the single point of issuing tokens to your clients. It can issue tokens regardless of the authentication method used. So it then doesn't matter whether the user authenticated with Google or a password, the client will still get the same access token.
Ad.2. When the AS issues token to your client, then you don't have any problems validating that token. The client doesn't care if the user authenticated with Google or not, it's not relevant in this case.
If you decide to skip using an AS and let the client receive tokens directly from Google, then you can still verify them. An ID token is a JWT and can be easily validated with a JWT library using verification keys provided by Google. Access tokens returned by Google are opaque tokens (If I remember correctly), and you need to check whether Google exposes an endpoint to verify them.
Ad.3. That is the general practice. When the user authenticates with Google and you notice that you don't have that user's data in your system, then you take the information from Google's ID token and create a user entry in your system.
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.
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.
We are building an application with a React/Redux frontend and a NodeJS/Express Backend. I, not being a security expert, opted to go with Auth0 to handle Authentication.
Auth0 returns an ID Token and an Access Token when a user logs in, this access token is used to authenticate and access our backend API.
We've seen this Access token stored before in Local Storage but Auth0 then contradicts that here. Furthermore, in this answer it seems that some recommend storing in Local Storage, as does this one.
This has me terribly confused. How can we store and persist the token without storing it in memory? We could store it in Redux only but it'll clear on refresh which isn't a solution.
Here they show that the User Signs in and the Access Token is returned and that later it is to be sent along with API Requests, which I understand, but where is it to be stored in the meantime?
How are we supposed to store the access tokens so our application can access our API? Or are we not supposed to store it at all?
We decided to store access tokens in a React Context Provider. Looks like Auth0 has updated their quickstart guide to do the same.
The best way to store AT/RT is by using a distibuted cache memory for your client backend servers. By this way, you make sure that all API calls must transite by your backend application. In your frontend, you pass only the ID_Token witch has to be used to identify your end users.
User sends ID_Token --> Client (backend web app) checks the Id_Token and Get AT from cache memory --> Call the APIs with AT.
I have used Auth0 for a while with success, I recently came across a new challenge: allowing external developers to access my API with credentials provided by my web app.
The current system comprises of:
a Web App (not a SPA currently) with Auth0 log in
a back end API with Auth0 api authentication
Currently there is a single client in Auth0. The user logs in on the website and when they call the API via the website the token is passed along in the headers.
My question is: what is the best way to allow developers to request direct access to the api, in a self service manner on my website?
I see two paths forward, either create a client for each developer application via the Auth0 management API (github style), or request a token on behalf of the developer with a VERY long lifespan (like AppVeyor).
I'm assuming that your API provides functionality and/or resources that are associated or owned by an end-user, and you want to allow other application to also access this data on behalf of each end-user. If this isn't the case, and you API is general-purpose and does not require the notion of an end-user identity then other approaches like API keys could also meet your requirements.
Considering the end-user delegation scenario, the approach I would recommend would be going with the creation of separate client applications within Auth0. Like you said, you could automate this process through the Management API so that this process could be handled in a self-service way. Despite being self-service, the application that enabled the registration could still apply constraints in order to make sure only eligible developers could obtain the necessary information to then obtain access tokens to access the API.
This has the benefit that if you wanted to stop an existing developer from using your API you could just remove the associated client application and they wouldn't be allowed to request access tokens anymore and the ones they already had would be short lived and soon expire. This requirement is more complex to implement when using long-lived tokens because they would need to be revoked/blacklisted.
A final note, if these applications don't require to act on behalf an end-user when calling your API and you would prefer to still accept access tokens instead of using a different approach like API keys, then you can consider registering client applications meant to use the client credentials grant.