Suppose my site is example.com
When a user at a client.com wants to login via example.com (with oauth2)
He comes to oauth.example.com/authorize and oauth.example.com knows he's not signed in to web.example.com .
oauth.example.com redirects him to web.example.com
he logs into web.example.com then gets redirect back to oauth.example.com
oauth.example.com somehow knows that he is logged into web.example.com
oauth.example.com does its oauth2 magic and sends him back to client.com
My question is, how should oauth.example.com should detect if a user is logged in or not with web.example.com .
I'm considering to let web.example.com to store session data in DB, and have oauth.example.com to look up the db.
My concern is that when session expires (without user explicitly logging out), it might be possible for the two servers get out of time-sync.
A user (A) might refresh web.example.com and find out his session is expired and leave the computer open.
Another user (B) might click login with example.com and oauth.example.com might consider (A) user is still logged in (because time is not well synchronized).
Would synchronizing clock with nptd be best I could do?
Or should I scrap this idea and come up with something else?
implementation detail: I'm considering spring-session-jdbc, and it unfortunately doesn't remove session data on every expiration.
Your oauth.example.com should provide the login page. The oauth.example.com must be Authorization server (rfc6749). When the web.example.com request user login, the login url should redirect to the oauth.example.com login page.
The oauth.example.com provider login authentication (identity verify), then back the web.example.com. If login success, the web.example.com will switch token with oauth.example.com.
I'm considering to let web.example.com to store session data in DB, and have oauth.example.com to look up the db.
You can treat the Oauth access token and Oauth refresh token as cookies or a session id for oauth.example.com in your web.example.com server.
My concern is that when session expires (without user explicitly logging out), it might be possible for the two servers get out of time-sync.
The oauth.example.com must have revoke token api.
Related
Does ORY Hydra currently have a feature that verifies if a client is logged in via OpenID Connect? I notice there is an API to logout via front-channel
When a user revisits the identity provider, however, I have no way of knowing if they are currently logged in or not. They could delete their client-side HTTP cookies and then I am out of sync with Hydra. Meaning: Hydra has them as logged in, but I have them now as logged out. Also, in the event of a back-channel logout, I want to be able to query for this state.
Is there an API I am overlooking that allows me to know whether a client currently has an active OpenID Connect login via Hydra?
It appears as of right now the only thing one can do is redirect the user to the authorization endpoint since we have no way of knowing if they are authorized or not.
The following two tables that ship with Hydra seem to be the source of truth for the data I am after: hydra_oauth2_access and hydra_oauth2_authentication_session. Does it ever make sense to query those directly if there is no supported HTTP API out of the box to see if a user has an active authentication session?
Sending an authentication request via a redirect to the Provider including prompt=none addresses this use case: it will silently login and return new tokens if there's an ongoing SSO session at the Provider, it will return an error code login_required if not.
Notice there will never be explicit user interaction in both cases so this is convenient (and meant) to run in an hidden iframe.
LOGGED IN STATE
An OAuth client is most commonly a UI application with multiple users. Each user's logged in state is represented by an Authorization Server session cookie that neither the application or user have access to:
The Authorization Server (AS) issues an SSO cookie, to be stored in the system browser for the AS domain
Both Web UIs and Native UIs send it implicitly on subsequent requests, when they invoke the system browser
AUTHORIZATION REDIRECTS
When an OAuth UI redirects the user, it is generally unknown whether:
The user will be prompted to login
The user will be signed in silently (eg the user could have signed in to another app)
For a Web UI it is possible to send an authorization redirect on a hidden iframe with a prompt=none parameter. If the user needs to sign in a login_required error code will be returned. See my Silent Token Renewal Page for further details.
This is not fully reliable however, and has some browser issues in 2020. Also it may be unsuitable if you are using a different type of client.
FEDERATED LOGINS
In some setups the AS redirects further to an Identity Provider (IDP), and the user's login state is further influenced by an IDP session cookie.
There is no way for an app to get hold of the user's IDP login state, since the app only ever interacts with the AS.
IS THERE A USABILITY PROBLEM?
If so, post back and we can discuss further ...
We have an ASP.NET MVC application that uses Okta for user authentication.
When an unauthenticated user browses to our app, they are redirected to Okta to log in and are then redirected back to the application, authenticated. When they click "Logout" within the application, they are signed out of the application and signed out of Okta.
The issue is when we click "Logout" from the Okta dashboard. When a user clicks "Logout" from the Okta dashboard, they are signed out of Okta but not signed out of our application. When the user logs in with different credentials in Okta and opens the application, HttpContext.User.Identity still contains the previous user information.
Is it possible to set things up such that when a user clicks "Logout" within the Okta dashboard they are also logged out of the ASP.NET application? What's the best way to accomplish this?
This is the expected behavior, let me explain.
Let's assume a user is not logged into Okta OR your application. When a user visits your application and clicks "Log In", they are then redirected to Okta to authenticate. When they authenticate to Okta, a new session cookie is created so the user's identity is remembered on the Okta domain (for example, blah.okta.com).
Then the user is redirected BACK to your application (yourwebsite.com) where they will have an access token and a NEW session cookie (on the yourwebsite.com domain) which will keep them logged in there.
So at this point, there are two separate sessions that are active:
One on your domain (yourwebsite.com)
One on Okta's domain (blah.okta.com)
When a user logs out of Okta's dashboard, this means that their token is revoked and the session cookie is deleted (from the Okta blah.okta.com domain). BUT, there is no way for Okta to delete the session cookie from YOUR website (yourwebsite.com).
Therefore, when your user does something on your website (yourwebsite.com), the user's browser will STILL send the session cookie to your backend that contains an Okta access token.
And... Depending on how your web application is configured, it will do one of two things to verify that token:
It can either validate the token locally using a JSON web token library (which is the default behavior), in which case the token is still valid, so the user is considered "authenticated" and will continue to be able doing things even though their token has been revoked.
It can validate the token against Okta's authorization server (this is called token introspection), which is a bit slower as it requires an HTTP request to Okta. If this is done, then the user will indeed be recognized as logged out and their session will be destroyed.
So basically, to get the behavior you're talking about, you need to modify the way your web application is validating the user's tokens. You need to switch from using LOCAL VALIDATION to TOKEN INTROSPECTION.
Unfortunately, we don't yet have the option to use token introspection in our ASP.NET library. The author of the library has just added that to her backlog =)
I've a site which will hopefully use a third party service for logging in (through use of OAuth2 and OIDC). I understand 90% of the process involved but am failing to get what I see as the final step. I'll describe the steps as I see them here and maybe someone can help me fill in the gaps. In my set up the Resource Server and Authorisation servers are the same machine.
This is the login process as I envisage it.
User comes to my site (let's call it Site A) and clicks login
They're redirected to the authentication site (Site B) where they
input their username / password.
Assuming correct credentials they're then redirected back to Site A with an auth code.
Site A takes this auth code and in a back channel communicates with Site B
again asking to exchange the code for a token.
Site B provides an access token to Site A (not to the end user, to the server)
Site A then communicates with Site B again (Resource and Authentication servers are the same in this scenario) and gets the relevant user detail.
So the user is authenticated and we know what claims they have, however, what I don't get in the above scenario is how Site A knows who I (the end user) am.
I never logged in on Site A so presumably no cookie was set. Basically I've gone to the site, been redirected to another site, logged in there and then am redirected back to Site A but is there a cookie set at that last redirect to identify me?
I've read plenty about this online but haven't found a clear answer.
Also, am I correct in thinking that in authorization code flow that the access token never gets to the user but instead resides on the application server?
If you really want to know who the user is on SiteA, it has to be the user from SiteA's own user database. It makes sense if SiteA is not just a proxy for SiteB's API and has its own users, permissions and functionality.
To figure out who the user is on SiteA you will need to match all your SiteA's users with Auth Server's users.
Part 1. Import your existing users into Auth Server
If you control Auth Server, import all your current users into its user database. Every one of them will have Subject ID (Id on Auth Server side). Copy those IDs back to corresponding users in your SiteA's db: your SiteA's User table will have new column, for example:
userid, user_name, user_last_name, user_auth_id (new column)
if you can't import all your users, it gets complicated. The only way I can think of: you will have to log those users in twice - once into OIDC provider and once in SiteA and then associate SiteA's user with OIDC user.
Part 2. Matching the incoming user to the internal user in SiteA
In successful response from OIDC Server you will get ID Token back. It contains sub claim with Subject ID of the user. When you've got that, you will need to do a lookup in your internal DB and find a corresponding SiteA's user. If you did not find one, create a new user at SiteA (if all existing users had been imported)
Once you know who the user is, log them in to SiteA like you would normally do (give them a cookie for example).
OpenID Connect auth servers provide the userinfo endpoint, which Site A can use for getting info about the user who authorized the access token (or the authorization code). For the auth provider (Site B) to be able to do it, it needs to keep association between a token and its user. So there is no cookie for this purpose.
You are correct about the auth code flow - the access token stays at the backend - there is no need to send it to the frontend / user.
To be able to pair the tokens kept at the SiteA backend with the consequent requests from the browser, you have few options:
You can use a backend session with cookies, which is very easy, because most backend frameworks have a built-in support for it. The cookie is sent automatically with each request and the tokens can be stored in a session object. This solution may be harder to scale - if you need a cluster.
You can create your own session implementation - either by using cookies or by some identifier expected on REST API as the Authorization HTTP header value. The backend session data can be kept in some distributed storage, such as Hazelcast or database. The session identifier can be in form of signed JWT, so you can keep user info in it.
Is it possible to authenticate a user using Google OAuth without forcing the user to choose allow / deny (ie. is it possible to "auto-authenticate") when I already have the user's refresh token, but their session with the application is no longer active?
Such as:
The user is using a different computer
The user is using a different browser on the same computer
The user's computer is re-imaged on every restart / cookies cleared on restart
Our session cookie expired
Note that I've set approval_prompt=force since I need the refresh token. Thanks.
Depends what you want to do... no user interaction is required to use a refresh token to get a new refresh token for whatever the scopes were. But a refresh token can’t be used to verify user presence, its whole point is to do this stuff when the user is absent.
If what you need to do is test that the user is present, you have to go through some sort of authentication interaction, with one exception. If you know the email address and do an OpenID Connect login with a scope like "openid email" and you send the email that you know about along using the login_hint parameter, then if that email user is present and signed in, your operation will succeed with no interaction required. Some useful details are at https://developers.google.com/accounts/docs/OAuth2WebServer
I am implementing a login process for my app, for that I have created a login screen and a sign-in button. So if the user is not signed in I have a register button which opens another form so that the user can register himself, after which I have provided a Done button which when clicked will send the information to the server and sends an authentication code to the users email address that the user entered in the iPhone app. Then the user will be registered.
So now I want to know what are the best ways to send the username and password to the server once the user is logged in? How is it possible to save the user name and password so that when at later time when the user opens an application he should not be allowed to login again?
The easiest way for secure transmission of the credentials is to use Https. On successful authentication you'll receive a "cookie" that you can store locally in the user defaults. That cookie will typically expire. So, on subsequent logins, you can check that the cookie hasn't expired, and continue to use it for your server communication.
If the cookie does expire, then you prompt the user to login again, thereby receiving a new cookie from the server.
Storing any user credentials on the device is a big no no. The only way you can do it is to store a hash of the password. You would still need to check a hash of the entered password with the stored hash to check they are equal. It doesn't really give you anything other than a local - no server required - authentication.
Of course don't forget that without having to login again, the app will be vulnerable. Someone else could use the app and the owner's server session would still be active.