Authentication flow for temporary credentials in the browser - authentication

I'm trying to wrap my head around a specific proprietary authentication flow used by one of our customers, and how to implement it in IdentityServer4.
We're developing an SPA with some microservices as backend and do all our authentication/authorization with IdentityServer4. The standard workflow for the SPA is (as expected, I guess) the implicit flow using oidc-client-js (for now).
Now the problem: one of our customers has something like a homebrew SSO solution dating way back. Users basically authenticate at a central portal and get a link to the application with a token attached. This token is valid for a few minutes and contains the temporary user credentials, I need to somehow authenticate at our IdentityServer.
My first attempt was the client credentials flow. Doesn't work, as the client cannot refresh its access token later, once the initial credential token ran out (the client does not and cannot have access to permanent credentials.) My current approach would be to kind of "hijack" the implicit flow, by authenticating with the given temporary credentials and from there on out use the normal refresh cycle without further need for any credentials.
Is this a valid approach or am I completely on the wrong track? If it's valid: how do I get IdentityServer4 to do my bidding? I cannot use IResourceOwnerPasswordValidator, because that would require the client credentials flow (I think?). Is an IExtensionGrantValidator the way to go? (If so: any ideas, how to convince oidc-client-js to use a custom grant?)
Thanks for your help.
Regards,
Markus

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.

Questions about Native applications and openId Authorization code flow

I have a few concerns with an OpenId Connect strategy that I would like to use and have been unable to find specifics on what the security concerns may be and any glaring issues with it I am overlooking.
Currently, I have an OpenId Connect implementation using Openiddict with Authorization Code flow. For the client, I have a React-Native app using react-native-app-auth.
I see from other questions on SO and from issues posted on the Openiddict repo that the recommended approach to third-party providers (e.g. Google) is: Client -> Auth server -> Google Auth -> Auth server -> Client/Auth server code and token exchange
However, it seems that a better approach from a UX standpoint (when using a SPA or native app) would be to implement something similar to GoogleSignIn on the client and either handle the identity on the server using an IdToken or authorization code from Google. This introduces an issue as the flow previously recommended could not be used as the entire initial challenge and redirect from Auth server to Google Auth has been skipped.
I have seen that this issue is mitigated by not using the authorization code grant and instead implementing a custom assertion grant. This seems to be an alright approach but would require exposing a custom grant and handling the flow differently on the client and server for local and third-party logins.
My proposed solution continues to use the authorization code flow and instead of adding a custom grant type the client could just pass a third-party identifier "Google" and the token or authorization code in the additional parameters of the OIDC authorize request. The authorize endpoint could then detect the provider and token, perform token validation, create a user or principal from it, and create an authorization code to send back to the client for the code/token exchange. This flow would look like the following:
1. Get the id token from the provider Client -> GoogleSignIn -> Client
2. Pass token to auth server and initiate code / token exchange Client -> Auth Server -> Auth server Verify Google IdToken (JWKS, issuer, audience, provider specific validation, etc...) or exchange auth code -> Auth server -> Client/Auth server code and token exchange
One downside to this approach would be the additional hops to verify the token on the server side. If the token was returned from GoogleSignIn, they themselves said that it could be trusted. https://developers.google.com/identity/protocols/oauth2/openid-connect#obtainuserinfo
I see that it is generally recommended to place the auth server between the client and the third-party but in this process the server is still between the client and auth server but only after the initial exchange from the client and third-party.
Questions,
In general am I missing something with this flow?
In this case would it be necessary to verify the token on the server side?
Is there some better way to approach this that I have completely overlooked?
Am I making this too complicated and UX should not be this much of a concern?
Instead of adding the provider and token to the additional parameters would it make more sense to pass it in the body of a post request? I don't see the issue with passing it via query string but that's also part of the reasoning for the authorization code grant from my understanding.
Apologies in advance for anything I have missed or omitted for brevity that should have been included.
Thanks.
ARCHITECTURE
I'm not sure I understand the UX problem - your existing architecture feels really good. If you want to login directly to Google, just send an acr_values=google query parameter in the authorization redirect, to bypass any authentication selection screens. The exact value will depend on how Openiddict represents the Google authentication option, and some providers use a non-standard parameter such as idp. Have a closer look at the OIDC request parameters.
A key OAuth goal is that the Authorization Server (AS) - Openiddict in your case - shields your apps from all of the provider differences and deals with their nuances and vendor specific behaviour. Your apps then also only receive one type of token, and only ever use simple code. As an example, the Curity AS supports all of these options, none of which requires any code in applications.
APPAUTH AND UX
If a user is already signed in then it can, as you say, look unnatural to spin up the system browser and them it is dismissed immediately.
A common option is to show the consent screen or an interstitial page to keep the user informed - and the user clicks one extra button. This can also be useful for getting password autofill to work. My code example and blog post shows how this might look, though of course you can improve on my basic UX.
OFFLINE ACCESS
I find this term misleading, since refresh tokens are most commonly used when the user is there. Are you just asking how to deal with tokens in a mobile client? Aim for behaviour like this:
Standard messages for API calls with access tokens in an authorization bearer header
Standard refresh token grant messages to refresh access tokens - eg as in this code
Note also that mobile apps can save tokens to encrypted secure mobile storage that is private to the app. This can improve usability, eg by avoiding logins every time the app is restarted. You should think through scenarios such as stolen devices and token lifetimes though.

Auth0 embedded login flow

We are trying to implement Auth0 in our next+fastify based application. The login page is custom and we want to integrate the login using the embedded login from the fastify server.
I am naive to oAuth and Auth0, I have a few doubts around it:
How do we verify the token? Do we verify the JWT and maintain the token on or fastify server or should we always the validate the token on Auth0 endpoint? I tried calling the userinfo endpoint which resulted in rate limiting. So, I interpret if we just verify the JWT on server instead of sending to Auth0 server. Also we send and maintain the JWT in cookies to validate the client always. Is the understading correct?
Is embedded login safe enough to be used in production? Are there any risk associated around it?
Is the approach correct? Is there any alternative way to implement the login flow? We also need to integrate reset password and rest of the functionality. I have read the SDK docs and it seems to have support for all.
Thanks a lot in advance
There are several options to validate a token issued by auth0, they recommend you to take advantage of middleware to verify the token. Multiple frameworks have their own middleware to check and validate JWT. It's as easy as integrate middleware with your application and perform validation when you need it. Check this:
https://auth0.com/docs/tokens/json-web-tokens/validate-json-web-tokens
In my opinion, it is always better to go with the Universal Login option of auth0, since embedded login sometimes incur into the cross origin authentication issue. Remember, when a user tries to log into your application using auth0, it redirects the user to another domain that differs from the one serving your application. In my experience, using the universal login provides you more information about the login process of your users, and that makes the process of debugging errors and auth processes easier. You can read more about login with auth0 here:
https://auth0.com/docs/login/embedded-login
https://auth0.com/docs/login/embedded-login/cross-origin-authentication
Yep, you can integrate the reset password process, which is almost entirely handled by auth0 itself. As I said earlier, we use Universal Login for our applications since it provides more control over the authentication flow. That doesn't mean you can't use Embedded login, it is a very good option too, but it seems more focused in UX rather than control auth flow.
Check this link if you still have doubts about the best approach: https://auth0.com/docs/universal-login/universal-vs-embedded-login

Web API security using tokens

I have built a Web API and now I am trying to determine the best approach to secure it.
I would like to use tokens along with credentials and thus, once the user is validated, on future requests a token can be passed with the http request. This API will always be called by one particular account and the username/password will always remain the same.
I am working with an already existing site backend, which has its own login implemented and stores user data. So I would like to stay away from creating new database tables to store user records. For that reason, I think implementing .Net Identity is maybe a overkill.
One of the options I am thinking of is grabbing the credentials from the http request and attempting the SQL connection with it. If the connection passes, then the user is legit. If it does not, it means I have to return access denied. Is this a good way of going about it? If yes, what can I use for token generation and validation?
Check out this guide which is specific for Oauth tokens with .NET:
OAuth with JSON Web Tokens In .NET
Also, make sure to follow the guideliness, because tokens must expire and be renewed after a while, for security reasons. You shoudn't use a permanent token, of course.

Is the OAuth2 implicit flow always 3-legged?

I'm setting up a web service with OAuth2 authorization/authentication. If I understand correctly, the implicit flow should be used for native desktop apps, because decompilation and other processes could potentially expose the client secret.
Implicit flow requires a valid redirect URI, but I don't understand how these should be used. I am not looking for 3-legged authentication through a facebook app or something, but 2-legged with direct access to my own web services. Like the Facebook and Twitter apps themselves do.
My question is: is OAuth2 implicit flow always 3-legged? And if so, how do Facebook and Twitter's apps ensure that the client secret isn't leaked? If they are using implicit flow, how does their redirecting scheme work?
I had the same question today and couldn't find any answers or posts either.
So what I have discovered so far:
1) Yes, implicit grant flow always consists of two/three steps (depending on how you count):
User is redirected to the authorisation page;
User confirms he grants access to this app;
User is redirected back to the consumer app, access token is passed as a hash fragment parameter.
2) Client secret is not used at all with implicit grant flow. It wouldn't make sense anyway - it would be in the plain sight. However, there are still some security measures: implicit grant usually requires a pre-approved redirect URL, so only specified trusted URL will ever get an access token.
3) Yes, I also noticed that even though Facebook/Twitter use OAuth2 heavily, you won't see these steps when you use their own web application. I have several suspicions:
They may not use OAuth2 for their own web apps at all;
They may pass the token using their own, non-documented flow;
They may pre-authorize their own apps so that authorization step is skipped.
I personally chose the latter option for my application. I created a list of internal applications that don't require explicit approval from the user.
Redirect-URI is necessary because the service provider needs to redirect back to your application after the login/user-consent. In case of the desktop application, you will probably open a browser for the login/user-consent and need to get the authorization code or access token back into your desktop application.
Basically there are 3 ways to do this: Using OAuth 2 with desktop c# Application
Google nicely describes the problematic and available options:
https://developers.google.com/accounts/docs/OAuth2InstalledApp