Authentication with my existing login system after Facebook Login? - authentication

I have a web application built using React that has an existing User/Session system. Right now, username and password are passed to server to authenticate and create session.
Enter Facebook Login (web). I want to allow for both username/password and also Facebook Login. So, now Facebook Dialog box appears and users can connect. I now receive the Facebook User Id and access token (short-life) on the client side (not the server side). How, now do I authenticate this user on my existing system and create a session?
If I use just the user id, this reveals a security issue (anyone can authenticate with a known user id and get a hijacked session). The short-lived access token is just that, short-lived. So that can't be used as an effective "password". So, what is the best way to securely authenticate someone on my existing login system if they've authenticated themselves via Facebook.
Thanks so much.

Found another user with the same issue here. It was resolved by the following:
The Facebook login request returns user id + short lived access token (client side).
Use the server side Facebook SDK to check the validity of the access token (will return user_id and app_id fields if valid).
You can trust the user_id field returned from the Facebook API to check against your existing user database.

Related

Authenticating multiple web applications through single authentication mechanism

How can I authenticate multiple applications with a single authentication mechanism?. These applications are having existing authentication within them, perhaps I need to authenticate these apps into my system which is isolated from others. Please suggest a better approach
When using OpenID Connect, the first application the user logs in to, will redirect the user's browser to the authorization server (AS). Since the user does not have a session between the browser and the AS, it will present the login screen. The user signs in and is redirected to the application (client) with an ID token and access token. The application will then establish a session between the browser and the application (typically a cookie)
When the user navigates to the second application, it will also redirect the user to the AS, but now the user already has a valid session between the browser and the AS, so the AS won't show the login screen (it may show the consent screen if the user has not consented to the requested scopes), and will issue an ID token and access token to the second application.
Now the user has a authenticated session with both applications with a single sign on (SSO).
If you use OAuth 2.0 with OIDC, you can authenticate your user once and verify the access token at each app the user visits. This is a typical single sign-on flow (SSO).

How to use Google Identity to log in from multiple devices?

How can I use Google Identity platform as a login / registration system for my own service?
Specifically - how can I do this and support login for same user from different devices?
Using for web service, nodejs without npm modules: passportjs / googleapis / google-auth-library.
My idea:
User opens myClientApp/login page and clicks on GoogleLogIn button which will ask him to authorize my service for specific scopes of his Google account.
I then get the refresh token & access token and save it in DB, then send the refresh token to the client with cookie.
Whenever I make a call to my own service API I send the refresh token from the cookie.
As long as I have valid access token saved in my DB or the refresh token is not expired - I treat the user matching that refresh token as an active session for my service.
Security problems:
cookies attacks, and the refresh token is easily accessed from the browser. Could use https / encryption and more methods to secure the cookie and it's value. Still- someone could copy the cookie from one computer to another!
Multiple login problems:
If the user login on different device, a new refresh token will be created. The previous device the user logged in to will now hold a wrong refresh token in the cookie...
Could the OpenID solve this? Do I need to use JWT?
What is the most secure way to use Google Identity login in my own service while supporting multiple devices login for the same user?
First, make sure that you really understand the security implications for what you want to do.
For example, NEVER send the Refresh Token to a client.
If you want to use the same tokens for the same client on multiple devices, you have a chicken and egg situation. How do you "authenticate" the user at each device. How do you know that user "John" is actually user "John" but on a different device the first time?
Your goal is not to trade convenience for less security. Your goal should always be security first, no matter the inconvenience.
A better approach is to let Google authenticate and authorize a user on each device. They only have to do this once per device. Your backend systems keep track of the Refresh Token issued for each device. You can then generate the Access Tokens and Identity Tokens when needed - they expire after one hour anyways. Store a cookie on the user's device that identifies them to your system so that you can look up who they are, get the Refresh Token, create new Access Tokens, etc.
There is a limit to the number of Refresh Tokens that can be issued before the oldest ones are voided. I think the number is 50. This is usually not a problem. If a Refresh Token is invalid, just put the user back thru the authenticate process and store the new token.
Also provide the user with a sign-out method that removes all stored tokens in your system.
The cookie that you store on the client's devices should be opaque meaning that there is no stored information in the cookie and the cookie is only valid for that device and no other devices. This solves the stolen cookie moved to another device problem.
I will now touch on some of your questions:
My idea: User opens myClientApp/login page and clicks on GoogleLogIn
button which will ask him to authorize my service for specific scopes
of his Google account.
Google OAuth does not work that way. You send the user to a URL, Google manages all display and input with the end user. Once everything is complete a callback URL on your server is called and you are passed a code. The exact details depend on the type of OAuth Flow that you are using.
I then get the refresh token & access token and save it in DB, then
send the refresh token to the client with cookie.
During the OAuth Flow you will request the Access Token, Refresh Token and Identity Token. The Refresh Token is saved in the database. Never send this token to the client. Read my suggestion above about creating an opaque cookie that you send to the client.
Security problems: cookies attacks, and the refresh token is easily
accessed from the browser. Could use https / encryption and more
methods to secure the cookie and it's value. Still- someone could copy
the cookie from one computer to another!
Create an opaque cookie that is only valid for that device and no other devices. If a client sends you a cookie intended for a different device, consider this a problem and invalidate all cookies, tokens, etc for this user on all devices.
Multiple login problems: If the user login on different device, a new
refresh token will be created. The previous device the user logged in
to will now hold a wrong refresh token in the cookie...
I covered this issue above. Store the Refresh Token generated for each device in your DB. Consider each device / Refresh Token / cookie as a set.
Could the OpenID solve this? Do I need to use JWT? What is the most
secure way to use Google Identity login in my own service while
supporting multiple devices login for the same user?
By Open ID I think you mean Open ID Connect (OIDC). This is already integrated into Google OAuth and this is the part that generates the Identity Token.
Do I need to use JWT?
Google OAuth Tokens are generated from Signed JWTs. However for the most part you do not need to worry about the format of tokens. Google provides endpoints that validate and decode Google OAuth tokens.
What is the most secure way to use Google Identity login in my own
service while supporting multiple devices login for the same user?
I covered this question in the first part of my answer above.

Authenticating Gmail addon user

My Gmail Addon is making a request to an external server.
I want to make sure on the server that it's really the user / the addon.
How can I do that? can I save a token in the addon that can't be tampered with?
(The addon interact with Google servers, can I take advantage on that?)
Authenticating the user (email address) in our server can also be of great help
We can authenticate the user by passing the accessToken & emailId of the user to our server, get the google profile of the user using this access token by making Google UserInfo API call, validate the email id from this profile against the emailId that is passed from Gmail add-on. If they both are same, you can treat it is a valid authentication. This process is similar to SIGNIN WITH GMAIL feature which we see in all apps nowadays.
Once it is authenticated, you can return the application session id to the add-on which we can save it in the user cache. This session id we can use to fetch our app data.
CacheService.getUserCache().put("sid", <sessionId>);

Is it mandatory to validate in my server the ID token with Google Sign in?

I implemented a simple web page where Google Sign In let users enter their Gmail and password in order to authenticate; then I made a simple server with Flask using Google Python API.
Everything is working fine, but I realized that I made the server before asking myself if I really need it: if I got it right, when user's credentials are verified after clicking on Google Sign In, the user is authenticated.
Client-side speaking, after a successful login a GoogleUser object is returned and it contains informations about the user; however, the user has already told me who he is since he provided me username and password.
So, why bother validating on a server an ID token if it is given after a successful login?
Some concepts sound contradictory to me: Google Sign-In for Websites: Authentication with backends video says that:
You can obtain an ID token upon the successful authentication
this would mean that the user is who he claims to be, but then, speaking about a server:
Note that the client libraries verify most of the information, but you still have to check if aud and iss claims are correct [on the server]
I thought that these two claims were verified on the client.
Is the GoogleUser object returned from a successful login enough to say "he is really that user"?
The ID token I send and verify in my server is necessary because there is no Google Sign-in button on the servers and is meant only for client side code?
So, why bother validating on a server an ID token if it is given after
a successful login?
The OAuth 2.0 ID Token provides the "verified" identity of the client. Since it is very easy to create an ID Token, you need to verify that the ID Token was created by a trusted Identity Provider. You verify the ID Token to prevent forgery attacks. How? By using the public key from the Identity Provider to verify the signature attached to the ID Token.
Note that the client libraries verify most of the information, but you
still have to check if aud and iss claims are correct [on the server]
I thought that these two claims were verified on the client.
In terms of security, you cannot trust anything from the client. You must verify everything. Hackers today think nothing of running scripts attacking any resource attached to a public IP address.
Is the GoogleUser object returned from a successful login enough to
say "he is really that user"?
No. The JavaScript code running at the browser can be modified. This means all data coming from the browser to your server should be consider "untrusted".
The ID token I send and verify in my server is necessary because there
is no Google Sign-in button on the servers and is meant only for
client side code?
You can implement 3-legged OAuth 2.0 which puts your server into the Authorization process. This way your server receives the Access Token, Refresh Token and ID Token. You then control what you provide to the client.

Single-sign-on authentication vs authorization

I'm implementing Facebook and Google SSO on my website using custom workflow (redirect urls, parsing on server side etc. - no javascript) and I got to the point I have access_token, token_type and expires_in and from Google also id_token and I am confused what to do next to authenticate the user.
I read a little about authorization vs authentication, and that Facebook and Google SSO is OAuth2 which provides authorization, but not authentication, from which I understand that this way my web application is authorized to do something on behalf of the user, but I cannot be sure the user is the one who I think he is? My main source is this: OAuth Authorization vs Authentication
So, my question is, what should I do to be able to can consider the user logged in.
Thank you
In your case google (and facebook) is authenticators. This services just tells your application that user who try to login to your system is the one who he wants to appear.
Assume you differentiate users by unique email.
Your application flow should be next:
The user try to login to application using google Application do all redirection google flow stuff and gives you tokens
Application need to store this tokens for future use
Application check if this user's email presented in database
If email is presented and google returns tokens (google authenticate your user successfully) you can login user in your app
If email isn't presented in database but google authenticate user successfully you can store this user (with email) to your database - sign it up - this is new user in your system
Same flow with Facebook. Surely you can extend this logic to be more your application specific.
SSO and OAuth are different. OAuth is authorization protocol.
You are dealing Google and Facebook oauth.
OAuth
In case of oauth, after successful authentication(google/facebook) you will get access token. You can use token for maintaining the user session.
With this token user is authorized, Now you should check whether the user is present in your database, if yes then authenticate the user and redirect to your application.
SSO
SSO is user authentication service. There are way to implementing SSO like kerberos SSO, ADFS SSO.
We should never use OAuth2 access token for authentication.
For details, please refer
https://oauth.net/articles/authentication/
The OpenIDConnect, built on top of OAuth2, can be used for authentication.
Google supports OpenIDConnect
https://developers.google.com/identity/protocols/OpenIDConnect
The basic idea is Google will issue the client app (your application) a ID Token after the user has login his Google account. You can then extract user information (e.g. email, unique user id) from this ID token and proceed your login flow.