OAuth 2 logout via browser - oauth

I have been reading the OAuth spec but am struggling to understand something about logging out.
Should I wish to sign out from a web app, does the spec provide a URL I can redirect a user to, that deletes their session including issued cookies?
I have found some docs that specify an endpoint I can make a DELETE request to, which revokes my tokens, but this does not revoke issued cookies?
I am imaging something like ${issuer}/v1/logout that when opened in the browser, ends the session.

In Open Id Connect there is an end session endpoint for this, though support varies between vendors. Here is a related answer I posted earlier.
What software are you using for the Authorization Server?

Related

Understanding the flow of OAuth2

I'm new to OAuth2 and I'm trying to understand the whole flow of things. For context, I'm thinking of making a web dashboard where users log in via Discord's OAuth2 API.
This is how I think the flow works based on my understanding so far:
User goes to my site and clicks a login link
My site redirects them to Discord with my client ID and a redirect URL #1 in the query string
Discord redirects them back to my site at redirect URL #1 with an authorisation code in the query string
My site takes this authorisation code and along with my client ID, client secret and redirect URL #2, uses all these to fetch an access token and refresh token from Discord
If I do get an access token, that means the user is now "logged in" (authorisation code worked)
My site finally redirects the user to a page and is now free to send requests to Discord's API with the access token, while saving the access token and refresh token. Just for example, say the page states their Discord username
I'm learning from this guide, and what confuses me is this code snippet from the guide. At line 5, it provides the redirect URL #2 mentioned above, in the query string. I'm not sure what it's for.
Also, I'm not very sure how to continue once I have the access token. If multiple users log in, I'd have multiple access tokens on hand. Say a user wants to access the page again, how do I uniquely identify them and know which access token to use to send requests to Discord's API? (for this example, the request would give me their username which I'd display on the page)
Yeah, I probably got a lot of concepts wrong. Any clarification would be greatly appreciated!
Edit: I've done more research into this, and found a much better guide here.
For my question about the second redirect URL, the examples in the official documentation specify a redirect_uri when doing both an access token and a refresh token exchange. However, this new guide makes do without for their access token exchange. Perhaps they missed it out? As this other stack overflow question says:
As an added measure of security, the server should verify that the redirect URL in this request matches exactly the redirect URL that was included in the initial authorization request for this authorization code. If the redirect URL does not match, the server rejects the request with an error.
I suppose this means that after the first access token exchange, any refresh token exchanges or straight up API requests with access tokens need to match the original redirect_uri of said first access token exchange. So I should use one and only one redirect_uri, and the refresh token exchanges/API requests do not actually use the redirect_uri, rather it's used for further security.
As for the whole login procedure, it seems I have to link the access & refresh tokens I obtain to a user session, and for that I'll look into using this passport strategy, passport-discord. Then, once the session expires, I'll discard the two tokens, and they'll have to click login again, but I can make use of this prompt option:
prompt controls how the authorization flow handles existing authorizations. If a user has previously authorized your application with the requested scopes and prompt is set to consent, it will request them to reapprove their authorisation. If set to none, it will skip the authorization screen and redirect them back to your redirect URI without requesting their authorization.
From there I think I'd just store the new access and refresh tokens associated with that user.
I'd really appreciate if any mistakes in my thought process could be pointed out!
Your summary seems good to me Mr Cloud - worth clarifying whether you are developing an SPA or (old) web app with a server side. Most commonly the first is cookieless, whereas the second stores a refresh token in a cookie. A key thing is to understand what the OAuth message workflow looks like. For SPAs and APIs this write up of mine may help you clarify what you want: https://authguidance.com/2017/09/26/basicspa-oauthworkflow/
Happy to answer any follow on questions ..
You can use the implicit grant to use with SPA
https://discord.com/developers/docs/topics/oauth2#implicit-grant

OpenID Connect: Possible to launch web page from application and automatically log in user?

We have a desktop application that requires the user to login. We're using OIDC (Auth code with PKCE) to do the login. I'd really like to be able to launch a browser and go to our website and log the user in automatically without resorting to anything dodgy.
From my understanding of OpenID Connect, I'm pretty sure this can't be done. Am I correct, or is there a mechanism I've missed?
This should work fine if the user has a valid session cookie with the OpenID Provider (OP) in the browser. There's no need to send something to the browser, as the user is already authenticated there.
When subsequently your native app requests authorization, the OP can authenticate the user based on the existing session, provided that request parameters like prompt, max_age and acr_values allow for that.

Where can i check if a google oauth 2.0 access_token is valid?

I am working on an a security module for an application, using google's oauth 2.0 access token using what's being suggested in the section "Obtaining OAuth 2.0 access tokens" on this article :https://developers.google.com/identity/protocols/OAuth2WebServer
I am storing the access_token received as part of the step 5 in the article above, "Step 5: Exchange authorization code for refresh and access tokens".
Lets say that the user goes to any google web app in the browser and logs out, I understand that google's session is invalid at that point that's fine and that is the session which the access_token i have stored was generated for, then, lets say that in that moment the user was logged into my app and my app's session expired so the problem is that if my app's session expires and the user goes to my app, my app will try to validate the access token ( i want to maintain my app's session somewhat align with the google session as long as the google session is alive ) but this service https://www.googleapis.com/oauth2/v2/tokeninfo does not intermediately reflect that the access_token i have in my app is invalid, it takes a lot of minutes to reflect that the user has logged out and the access token is not valid.
Please excuse my long explanation and i expect it is clear.
Now my question is, what google rest/service provides a better validation for the access_token?
I think you have a wrong assumption that an access token (and a refresh token) is bound to the session that was used when authenticating the user. I tried to find some info about it, but didn't succeed. There may be multiple sessions - for example in different browsers. If you log out in one browser, the other stays logged in, so there is probably no "global sign out" that would terminate all sessions of the user.
If the tokens were invalidated on the browser session logout, it would make the applications using the tokens fragile. For example mobile or desktop applications that use a browser just for authentication and don't use to keep the browser window open after successful authentication, so they cannot keep the browser session alive. Their tokens would get invalidated with the session expiration.
Google doesn't seem to provide OpenID Connect session management features in their discovery document, so you cannot monitor the session using iframes either (as described in the RFC).

Access LinkedIn REST API without front-end (e.g. OAuth2 redirect)

Goal
Fetch a company's updates save them locally in a background task
Problem
This should be done as a backend service without any real user interaction. We could provide a user account to use, but the authentication is a problem: There is literally no one to answer the OAuth redirect and there is no public redirect URL to configure, since it's a background service.
Is there any way to access the API without having a redirect URL or a real user?
You can get an initial access token in a regular front end flow, for you as the app developer i.e yourself as the LinkedIn user. Once you've got that, you can store it in the backend and use it for 60 days to get access to the LinkedIn APIs.
After 60 days you need to refresh the token as documented in:
https://developer.linkedin.com/documents/handling-errors-invalid-tokens
Unfortunately LinkedIn does not (yet) support an autonomous refresh flow where your app can get a new access token by presenting a refresh token on a backchannel. So the developer will have to refresh the access token by a manual login every 2 months.
Well, it is still all HTTP and HTML, so in fact there is no real reason to show the OAuth dialog to a user, as long you can strip out the necessary parts in the HTML authentication dialog and send a valid response back to the server, using the username and password from the user (which you can obtain from him, or save it yourself in a config file if it is you).
Note that there might be a legal issue if LinkedIn demands you to actually show the dialog, beside that, there is no technical need.

Dealing with expired access tokens in OAuth2 implicit grant

The specification of OAuth2 states that an authorization server must not issue a refresh token when using implicit grant. In our use case we protect a RESTful API with OAuth2 and use a Single Page Javascript application as a client for this API. As it would be very difficult to redirect to the authorization server after an access token has expired, we are searching for a better way to get a new valid token. I could think about two different approaches and wonder which one could be better:
Use a hidden iframe to Rerequest a valid access token. For this it is necessary to include a parameter like “prompt=none” which tells the OAuth provider neither to challenge authentication, nor to display an authorization page. If the user is authenticated and has authorized the application the server will send back an access token in the urls # parameters. If one of the previous conditions is not fulfilled, it will redirect with an error like #error=authentication%20lost. With this behaviour we can use short lived access tokens also with an implicit flow.
We could use an additional scope (e.g. offline) which tells the server to hand out a refresh token. Even if the original spec says that implicit flow does not issue refresh tokens (which is correct if the client only uses OAuth it for a first authorization) you are free to define your own scopes for your particular application. You should consider to only allow this scope from well-known clients.
Both approaches are very similar to those of OpenID Connect. Unfortunately there are not many implementations of OpenID Connect at the moment. So first step would be to extend the OAuth2 server until OIC will be more popular.
So which approach should be preferred?
EDIT: The token endpoint needs client authentication, which is only possible for confidential clients like server-side applications. With the second approach it would only be possible to let the RESTful API in our case the resource provider to refresh the token and send it back to the client. I think this would be a security risk. So probably we have only one valid approach.
I'm trying to achieve the exact same thing at the moment.
I've actually implemented hidden iframe approach and then realized you have to be very careful with iframes. Any malicious website can contain your iframe and get access token easily if you don't specify X-Frame-Options.
Best approach for refreshing token should be password grant as specified by the spec. (I wanted my users to login with their facebook account & implicit flow was easier to develop this. I have not quite figured out how to do this with password grant.)
2nd approach also came accross my mind and seems much safer than the 1st to me, since you can usually trust the https & browser storage to keep your tokens secret.
Edit
I realized, even with X-Frame-Options most browsers can't prevent redirects, because this header is attached to the response body and redirected URL will be exposed, therefore access tokens exposed.
Update
Looks like hash fragment is protected by the browser when accessed from the parent page within different domain. So I assume #access_token is safe. My bad. Just as a reminder callback page has to store the access token in its own right, instead of (my original intention) delegating it to the parent page like window.parent.storeAccessToken(hash); which obviously is a dumb thing to do.
From the OAuth0 website:
If you need to authenticate your users without a login page (for example, when the user is already logged in via SSO scenario) or get a new access_token (thus simulate refreshing an expired token), you can use Silent Authentication.
As for the Silent Authentication:
However, redirecting users away from your application is usually considered disruptive and should be avoided, from a UX perspective. Silent authentication lets you perform an authentication flow where Auth0 will only reply with redirects, and never with a login page.
This will allow you to log back the user using an SSO token, without having to prompt him for credentials again.

Resources