I'm manually writing OAuth2 Server Flow to allow users to login using Google (and other websites, but let's focus on Google).
I have the basic flow working:
user clicks on the login link.
goes to Google and sees consent screen.
accepts.
redirected back to my website.
server takes relevant information and logs user in.
So far so good. Now I want to make sure that the server remembers the user for next time. For that I store the token along with other user data on the server.
Now, how do I check, server-to-server, if the token is still valid? I have it's expiration time, so I know it's invalid after that time passes, but what do I do then? Should I ask for a permanent (offline) token if I only want to allow login?
As a result of authorization success from Google, you should also get refresh_token. If you are not getting then do the following.
when you are redirecting to Authorization endpoint add additional parameter access_type=offline which will make sure that you will get refresh_token
Use refresh token to get additional access tokens.
Now, for validating you can hit the token validation endpoint of Google, if you are not maintaining the state. If you are maintaining the state then you can validate the expiry of token if token is only signed, if encrypted then you have to validate from Google.
You can play with different Google OAuth URLs here
more details on token validation here
Related
I need to implement centralised authentication server with single sign on.
One of the requirements are, that there should be no intermediate login screen (a.k.a direct login from service provider), so OAuth2 with password grant seems like the best option here.
User is read-only, authentication is used only to access specific content, which is the same for all users, the users can't change their personal data or anything else. We use user ID as an username and date of birthday as a password, it's not really secure, but that's not something we can control, because we get credentials from other 3rd party service, though we still want to make everything secure as possible, because user data includes such personal data as full name and home address.
To make it clear, next I will describe how I imagine OAuth2 and SSO flow to work together:
User enters his credentials and submits the login form in service provider
Service provider (SP) sends a request to identity provider (IdP), to check if credentials are valid (Request is signed with client id and secret as a base64 bearer token: base64(client_id:secret))
If credentials are valid, IdP creates access token (5min) and refresh token (24h) and returns them to SP
On every user request, SP uses access token to receive user data from IdP
If token is expired, SP makes another request with refresh token to retrieve new access token. Request must be signed with client id and secret.
So it's pretty much, how OAuth2 password grant would work, probably hardest part is to make it work with SSO, I couldn't really find any working stateless implementations, so came up with this:
When access and refresh tokens are issued, IdP stores refresh token in a cookie.
When user visits SP for the first time, quick redirect to IdP is made, if refresh token exists in a cookie it’s added as query param to the redirect url and user is redirected back to SP. If no, some query param is added to identify, that user is not logged in, to avoid redirect loop.
SP uses retrieved refresh token to issue new access token (which is unique for every SP).
So access token can be used only by service provider, which it was issued for. And refresh token, can be used by all service providers, but to issue new access token client id and secret must be provided, so refresh token alone is useless.
Also forgot to mention that all websites use TLS.
What do you think about this implementation, is it secure enough? Maybe you have other suggestions?
I need to implement LinkedIn login for one of client. Here is the workflow I am maintaining,
User will click on the "LoginUsingLinkedIn" button for the fist time.
The user will be redirected to linkedin authorization page and if he authorizes , I am requesting for an access token and stroing the
same access token in the browser cookie. Now I am making call to linkedin to get the user info using this token.
Now lets say the user again come to the site after 2-3 days, then first I am checking if there is any accesstoken present in cookie.
3.1: If accesstoken is present in cookie, I am making a call to linkedin to get the email id, if its successful then the accesstoken
is valid and proceed further. If the call returns an error, then I am redirecting the user to linkedin authorization page agin.
3.2: If the accesstoken is not present in cookie, the user will be redirected to linkedin auth. page.
This is the first time I am integrating oauth login to any site. Please let me if there is any issue with this approach.
Is it safe to store the accesstoken in the browser cookie? OR shall we store the authorization code in the cookie and obtain the accesstoken every time? I am not sure if it make sense. Please help.
There are libraries for this, even if you do not want to use it is good to take a look, in my point of view it is better to store the values in the session or database.
If you need only login, and is not doing things on linkedin like the user, just get authorization if the user is not logged in and save the user information, then when the session has expired or if the user has logged off, get the authorization again.
https://github.com/thephpleague/oauth2-linkedin
https://github.com/thephpleague/oauth2-client
I integrated my website with the Linkedin OAuth api to retrieve the basic profile settings, and it is the only way to log in to my website (so logging in should go through Linkedin each time). The user has to grant permissions upon login. But this now happens on every login; I cannot manage to make Linkedin remember that the user has already granted access (so what I want is that the second time for it to just redirect back to my site automatically)
I receive an access token at every successful login, I save it in the database but can't find a way to use this in a subsequent request (I'm not even sure if this is how I'm supposed to do it?)
The endpoint I am using to login is:
"https://api.linkedin.com/uas/oauth/authorize?oauth_token=" . $token
Where $token is an oauth token
Please tell me how to make the subsequent requests without Linkedin asking permissions
thanks
You can try using php cookie or SESSION and setup expired date to next few years,
so every user visit your site your system will check into database with token which saved on cookie or SESSION, only this method can use if you don't want redirect user to linkedin page every they visit your site.
The oauth_token is only good for so long. You should be getting a new token each time you use the API not storing it in your database. Here is a link to the linkedin oath
https://developer-programs.linkedin.com/documents/getting-oauth-token-php
I've been trying to get Google's Calendar API working in a PHP web application, but I'm having a hard time getting authenticated.
What I want to do is to allow users to interact with calendars of a single account known by the server.
Each type of scenario covered in the OAuth 2.0 docs talks about "user consent" which involves a login form and the individual user logging in, but I want the server itself to authenticate directly and obtain an access token for itself.
Is there some part of OAuth or some alternative mechanism I can use to do this?
In order to do this, you must go through the steps for user consent and then copy the access tokens it gives you into the PHP code.
The usual procedure for OAuth is like this:
Send user to authentication page.
User comes back with $_GET['code']
Send $_GET['code'] to OAuth server for a token
Store token in database for the user (or session, if it's very short lived)
But when doing it with a single calendar like this, you modify step 4. Instead, you dump the token to screen and copy it into your PHP file as variables, instead of putting it in the database. Then when you go to pass the access token to the server, you just pass the known, static token rather than a dynamic token from the database / session.
See mathewh's answer here:
How to automate login to Google API to get OAuth 2.0 token to access known user account
The lightbulb for me is when you get the access token you get a refresh_token as well... you use this token to "refresh" your access token once it expires.
There is no way around a manual authorization step the first time.
I've implemented the oAuth in php (currently for twitter) and as I've read in several tutorials you should store the access token in db for future use. However I don't see how you know if you have the access token stored for a particular user to decide if you should pull it out of the db or regenerate it. Here's a flow describing my question:
First time user signs in:
get request token
send user to provider's authentication page
user returns to callback url with oauth token and oauth verifier
get access token
save access token/user_id/screen_name on db for future use
User returns 10 minutes later:
access token is still in server session vars if user didn't log out. else, repeat process.
User returns 1 month later:
get request token
send user to provider's authentication page
user returns to callback url with oauth token and oauth verifier
( at this point I only have oauth tokens, how can I know if the user has previously logged in with twitter and pull their access token from db? )
if it is the user's first loggin, generate access token.
The main workflow for oAuth is clear, however it is not clear how to handle returning users and which data should be stored or not.
A million thanks!
You should not regenerate token for each access. Generate it only when it's expired. I've build twitter application using OAuth. Here my flow:
when user login, I will check if they have token in DB
1.1. If it's not exists, authenticate them and then store and use the resulting token
1.2. If it's exists, use it.
1.2.1. If twitter doesn't complain, then the token still valid, use it.
1.2.2. If twitter complained, then the token is expired. Return to 1.1.
1.2.3. If after x retry twitter still complained. Something wrong, notify admin!
Here's the graphical explanation:
The only thing I believe is missing here, is generate a random (long and unguessable) user id first time the user joins the system, and store it forever. this way you can tell who's taking the actions