Who generates JWT when using Google OpenID Connect authnentication for my ASP.NET Core Web API app? - asp.net-core

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.

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.

OAuth and authentication

according to here (https://oauth.net/articles/authentication/) and many other things I have come across. OAuth is not meant to handle end user authentication. Reading through the article above and others while searching provides so much information at once from so many angles that it is hard to see through it all. ok...
Does this mean that...
A) The protocol itself is not intended to handle authentication, so therefore, OAuth client apps should inspect "who" can authorize users according to the OAuth providers?
If ONLY the user can authorize third party apps, then isn't the fact of receiving authorization from the OAuth provider in itself proof of authentication? (if this is the case, then can OAuth access tokens from places like Google and Facebook be trusted as authentications?)
B) OAuth client apps cannot trust authenticating users with OAuth, so therefore must provide another sound authentication mechanism alongside it?
If this is the case, then every site that I have clicked "Login With [provider]" (and no other complementary authentication scheme) has got authentication wrong?
It seems to me that if only trusted and specific OAuth providers are used, then this flow could infer authentication
App requests login with trusted providers
User is directed to provider to authorize (ONLY user can authorize)
App then requests and receives token from provider, and adds user to the app database if necessary.
Token is put into secure cookie or JWT and returned to the user to be presented on subsequent visits.
The purpose of OAuth2 access token is to delegate some access rights (scopes) from a user to a client application. So the application redirects the user to an authentication provider (OAuth2 server), which authenticates the user and asks the user (consent step) whether he/she wants to delegate some access rights (the scopes requested by the application) to the application.
If a client application receives an access token, it can get its meta data at the OAuth2 introspection endpoint - such as username of the user (resource owner). So this way, the OAuth2 can be used for authentication. But the main purpose of access tokens is to delegate some rights. For example if a third party application wants to save its data to a user's Google Drive, it needs an access token issued by Google with scopes that allow it to access Google Drive.
If you want to use OAuth2 only for authentication in your client application (to get identity of a user), you can use OpenId Connect (OAuth2 extension) and its ID token, which is in JWT format and contains information about the user that was authenticated the authentication provider. This is better suited for the "Login With ..." functionality.

Authentication using SAML

My client asked me to develop a web api and use SAML as authentication.
I came across with the image below from this site, that shows the authentication flow.
However I don't know how to use the token that is generated after the authentication.
Do I need to store it as any other session variable?
Do I have to renew the token after a certain time or it lasts during all the session?
Note: The authorization server / idP is maintained by other party.
Since you develop the web API yourself, there's no need to refresh the token.
You're API needs to be added as relying party to the IdP. After that you can redirect to the IdP and initiate authentication. The token you get back contains several attributes (also configurable on the IdP) like unique user-id (uid), e-mail, name, country, etc...
In most cases this token is signed using a public/private key. Your API server needs to verify the signature, the issuer (the IdP), the audience (your API) of the token and consume the attributes. When everything is OK, you'll need to provision a local user account, link the external uid and create a local authentication cookie (or generate a OAuth2 token if your API uses OAUth2 or OpenIdConnect) for the locally provisioned user account.
Since this is a complex process, depending on the language/framework you're using, you might want to look into existing implementations.

API oauth2 which grant type should I choose

I'm working on a personal project composed of an API and 4 clients (web, android, iOS, windows phone).
I'm using django-rest-framework and oauth2 toolkit on the API side and I wonder which grant_type would be more suitable in my situation.
I read somewhere that the implicit grant_type is appropriate for working with mobile clients.
I'm currently using the resource owner password credentials system.
My current workflow is:
The user creates an account on the API registration page (http://mysite/api/register) then gets redirected on the web client.
The user have to authenticate himself on the API from the web client (the secret and client ID are store in the web client). If the authentication is successful the access_token and refresh_token are both stored in the user session.
Each time the user want to access a page I verify if he is authenticated by requesting the API using his access_token. If the request fails, I retry with the refresh_token. If it's fails again I redirect the user on the auth page.
The user can use the API on a mobile client with the same account without extra manipulations (the secret and client ID are store in a secure location ex. share preferences or keychain)
I like this workflow, it's simple and convenient for the user: he registers once and can use all the clients and I get a perfect separation between the logic (API) and the UI (client). But I'm worried about the security of this system. I don't want to expose my users to threats. Do you guys have any thoughts, recommendations, suggestions?
You help in this matters would be very appreciated.
Thanks in advance!

REST API Authentication (maintaning an authenticated state)

I am developing a REST API. Currently I am trying to make it minimally secure. I am asking this question because most of the posts I found about this subject were quite old.
For authentication I found this schemes:
Basic authentication
AWS authentication protocol
OpenID
OpenID Connect
OAuth pseudo authentication
Basic Authentication and AWS authentication maintain the requests authenticated after a firts authentication because they keep sending signed requests.
I don't understand how the OpenID and OAuth authentication maintain a (second) request autehnticated? Do I need to check the access token with the OAuth/OpenID server per each request? How does this protects the REST API from receiving requests that have been altered?
Any other schemes that you recommend, advices or reading material about the subject are always welcome.
I'd talk about OAuth here
i) You create a web app and want to use google's OAuth API's.
ii) You register your app here and get credentials.
iii) Now, in the app you'd use Google's SDK to open the login page, enter your credentials and Google would verify it and send you access tokens and refresh tokens.
iv) You would make REST call to google's APIs with the access token and fetch user's data.
Now, coming to the question you asked -
An access token generally lives for 1 hour. Yes, any authenticated calls that you need to make to any of Google's API within one hour could be made with the same access token.
There is another type of token - the Refresh Token. At any time, your app can hit the provider's token exchange endpoint and exchange the refresh token for - refresh token + access token pair.
Now again, you have an access token that will help you for one hour and a refresh token that can be exchanged any time.
Refresh tokens live for as long as you want, till the time the user explicitly revokes permission to your app. (Tells Google that it doesn't not want you to access his resources!)
OAuth would make your REST API secure by ensuring that only authenticated and authorized clients can hit your API. But generally, OAuth is only used when there's a situation where a third party client needs access to a user's resource!