I have an app and I want to let people login using google sign-in. I need to check in the server what are the permissions of the current logged in user. (I have a table with email/role)
I read the documentation here:
https://developers.google.com/identity/sign-in/web/sign-in
from what I understand, when a user logs in using google, I get a callback and I can use the email and make calls to my server with it.
But what I don't understand is how can I make sure a malicious user won't see the javascript code and make a request to my server using any email he wants?
In other words, if the entire sign-in is in javascript, how can validate the identity in the server?
Assuming that you are doing the following:
Signing in from the Web
Using JavaScript for Sign-in and all data access
The following measures preventing malicious 3Ps from making API calls using your credentials / other user credentials:
API calls are domain-restricted to the authorized origins you configured in the developer console
API calls are restricted to the current credentials (e.g. only can get current user details / can only get credentials and tokens for the current user)
That said, let's move on to authN: making sure the user is who they claim to be. On the sign-in callback, you will receive a special token, the ID token, that has:
The audience for the token (your client ID)
The issuer of the token (user ID from profile)
An issued timestamp
An expiration timestamp
etc..
These values are used to prevent forgery and avoid the confused deputy problem. For example, you use these values to check claims of who the user is, that the issuer of the token was you, and that the token has not expired. You also look at the ID token signature and validate it either using JWT functionality or by passing it to the Google verify token endpoint.
After verifying the user using the ID token, you can set a cookie for establishing a session and avoid having to verify the user on every API call.
Google provides token verification samples here, for example, the Google+ Token Verification sample in Ruby. Additionally, the Google+ quickstart samples demonstrate establishing a client-server session in the "/connect" server endpoints on the server-side languages (Ruby, Python, .NET, etc).
Additional discussion on the topic is available in the Identity Cookbook.
Related
Sign in intent doesn't work at the moment as clearly explained in the docs, it's just something you can use for test in the emulator, but it's not available in production.
My case is I'm using account linking and my token expires after one day, so if the user doesn't interact with the assistant, the token will no longer be valid. Then if the token is proved as invalid on the webhook I want to send back 'please link your account again' to the assistant from the webhook.
There is a method app.askForSignIn(); which seems similar to what I need but it looks like it is not available for Dialogflow and only available for the SDK.
So what I have done is:
Make an intent in Dialogflow with the name actions.intent.SIGN_IN and added actions_intent_SIGN_IN event to it
When any request comes to the webhook I check the token, then if I encounter an invalid token I call app.askForSignIn();
What is happening:
The app just left the conversation e.g: test app left the conversation
When I say again "talk to test app" it is behaving like the account is linked and does not ask for account linking until I manually reset the whole app using the reset button from test console
Update:
I tried to use the code snippet from the doc (https://developers.google.com/actions/reference/nodejs/AssistantApp#askForSignIn)
and it is not working as well, here is the response from the simulator when I call app.askForSignIn(); from the webhook
You can have 2 tokens, one being the access token, which is short-lived, and the other being the refresh token which is long-lived.
So, When Google needs to call one of your service's APIs, Google uses these endpoints together to get permission from your users to call these APIs on their behalf. A typical OAuth 2.0 session initiated by Google has the following flow:
First, Google opens your authorization endpoint in the user's browser. The user signs in if not signed in already, and grants Google permission to access their data with your API if they haven't already granted permission.
Then, your service creates an authorization code and returns it to Google by redirecting the user's browser back to Google with the authorization code attached to the request.
Next, Google sends the authorization code to your token exchange endpoint, which verifies the authenticity of the code and returns an access token and a refresh token. The access token is a short-lived token that your service accepts as credentials to access APIs. The refresh token is a long-lived token that Google can store and use to acquire new access tokens when they expire.
Finally, Google calls your service's APIs, attaching the access token with each request. Your service verifies that the access token grants Google authorization to access the API, then completes the API call.
I have a problem understanding the principle handling of oauth 2.0 tokens.
My scenario is, I have a web based frontend backend system with node.js and angular 2.
A user should be able upload a video on this site. Then some additional metadata is created (dosen't matter for this question). When that is done, the user could upload the video to youtube with the additional data by clicking on a button.
My question is how many tokens/credentials are there in this process. The youtube api needs an oauth token. Does the user also have its own token?
Here is the tutorial I used:
https://ionicabizau.net/blog/14-uploading-videos-to-youtube-using-nodejs
As you can see one token for the API is created for local testing. But is this token generated in a different way in a live version? And how is the user of my website recognized. Also via this token? Or do I have to generate a second token for him?
I am not sure what you mean by 'Token'.
In order to access any Google API you will first need to register your application on Google Developer console. You will then need to create Oauth2 credentials. Oauth2 credentials is were your application will request access from a user to access the data on their YouTube account.
On Google Developer console you will need to save the Client id, client secret and the redirect uri. All three will be needed by your code to authenticate the user.
When the user grants your application access to their YouTube data. You will get an access token and a refresh token back from the authentication server. Access tokens are short lived about an hour and are used to make requests (like upload) to the API. A refresh token can be used to request a new access token once the one you have currently has expired.
You will probably end up with the following:
client id, client secrete, redirect uri, and a refresh token.
If you are interested I have a tutorial that is part of my Google Development for beginners tutorial series that explains Oauth2 and how it works.
An access token is generated from the Server side and sent back to client from where the access request is generated. For all the subsequent requests you need to pass the access token which will be verified with the signature of the token saved on the server to check the authentication of valid requests. You will only get 1 access token which will be used.
You can also use "Refresh" tokens in case you need to keep your access tokens valid for longer duration.
I know the issue of securing connexion between a JS app (let's say just 'app') and an OAuth2.0 server (let's say just 'server') is an age-old question.
However, I can not find a lot of information about the special case where the app and the server are coded by the same entity and stored at the same place (i.e. same domain, or at least, two subdomains of the same domain).
First of all, as far as the OAuth grant type is concerned, I think the right one is the Resource Owner Password Credentials Grant, since the server and the app have the same author. The issue here being that the Client ID and Client Secret are available to the user in the client. This can be dealt with either by developing a proxy on server end or by using short-life tokens and disabling CORS (if I understood correctly). Is there any other property we can take advantage of as far as security is concerned when server and app have the same author?
My second question relates to the optional use of a Facebook Login authentication (or whatever well-known app OAuth login system: Google, Twitter, etc.).
Ideally, I want users to log in using either:
My-app-related credentials (if they registered without using FB login option)
Facebook credentials (if they registered using FB login option)
The first log in method is the classical one: upon log in, are sent to the server the user credentials along with the client ID and client Secret, we get back an access token and everything works well.
I must confess I'm a bit lost with the second method: upon login, user Facebook credentials are sent to Facebook server, which responds with an access token, and my app get access to my user Facebook information (such as email address and UID). But I do not know what to do with this FB information, and especially what I should sent to my own OAuth server so that:
The user gets connected to my server
The connection is secure (i.e. no one can impersonate the user by only having to get her Facebook UID for instance).
In other terms, there should be something secret related to Facebook sent to my server but I can not figure what.
I have found the answer to my second question, so I share it here:
What should be passed on to the server is the Facebook access token, so that the server can :
make a request using Facebook PHP SDK and the given token
retrieve user data (such as Facebook UID for instance)
match it against your website user database (which should have users FB UIDs)
actually connects the user if there is a match
Step 1. and 2. can be done nicely with the helper class FacebookJavascriptLoginHelper of the FB PHP SDK. In this case, the access token is stored by Facebook Javascript SDK into a cookie that is read server-side by the FacebookJavascriptLoginHelper.
I want to import contacts of a Gmail user through the Google API.
I have the following:
Use Client secret and key to obtain the authorized url. This is the url which the user visits to allow permission for my app.
The authorized url redirects to the redirect uri specified in the App settings.
I have a query parameter code in the url and I am guessing this is the Authorized code that the docs say here.
The problem:
I want to exchange this code to obtain the access token and the refresh token through javascript if possible. But I can't see any docs for this part in javascript.
In my server side I am doing this to obtain the authorized url:
token = gdata.gauth.OAuth2Token(client_id=settings.GMAIL_CLIENT_ID,
client_secret=settings.GMAIL_API_KEY,
scope=scope, user_agent=user_agent)
auth_url = token.generate_authorize_url(redirect_uri=redirect_uri)
and then redirecting the user to auth_url. Now once the user is allowing the requested permissions they are redirected back to my site with the query parameter code. I want to use javascript from here to get the access token.
The other option is to get the access token in the server side once the user is redirected to my site and return it to him along with the response but I dont really want to do this.
Short answer: if you want to use OAuth2 client-side authentication, you're using the wrong documentation.
Now the details.
OAuth2 has 4 grant types:
Authorization Code,
Implicit,
Resource Owner Password Credentials and
Client Credentials
If you want more details, you can read this nice post with explanation.
You've pointed the Google docs for OAuth2 for Web Servers, which fits Authorization Code type. It relies on Web Server data exchange over SSL, because it involves exchange the client_secret.
I.e, if you try do the POST request to get the access_token using JavaScript, you'll expose your client_secret, as it's a required parameter in the POST call.
If you want try request the access_token not using server side code, you need to use the Implicit grant type.
You can find Google documentation for Implicit grant type in Using OAuth 2.0 for Client-side Applications
I am trying to wrap my head around the G+ Sign-in flow, but I am not sure if I have gotten it right.
I have mainly been looking at this page
Where in that flow can I connect to my own database and fetch things such as username and permissions, and what am I supposed to store as identifier in my database (to quickly identify them next logon)? Should I talk to the G+ API and get their G+ ID and then store that (together with the data I want to store about the user)?
How would the flow look the second time they sign-on?
I need something that will in the end give me the G+ ID (if I used that) so that I can find them in my DB.
The quickest way to get going with Google+ API calls is the Google+ Quickstarts. These samples will get you going with code that should be ready to copy and paste into your applications. I'll shortly discuss the flows demonstrated in the apps.
As with OAuth 2.0, the goal is to get a bearer token (access token in OAuth 2.0) to authorize API calls. The token can be retrieved a number of ways, but the most important for sign-in using the Google+ Sign-In button is code exchange.
The first time a user encounters your site (let's call it sign-up) the flow will be code exchange. The code exchange pattern is:
User reaches your site
User clicks preferred authorization (Google+ Sign-In)
User is presented with consent / authorization screen
Code is returned from JavaScript to the web client
The Web client (HTML/JavaScript) passes the authorization code to your server
The server exchanges the code for a refresh and access token then caches these tokens
At this point, your server has an access token. This means that you can make API calls (e.g. plus.people.get('me'), which gets the signed-in user's profile) to Google based on the user permissions granted to your app.
The user should now be authorized with your server and authentication should happen based on the user's session and so forth. However, now you have a new problem, what happens when the user accesses your site again from a new browser, or otherwise destroys their session?
This is a great time to transition to the next important flow: the authentication (let's just call it "sign-in") flow. For sign-in, you should have the client pass your server an authentication credential (again a bearer token) and then verify the credential before establishing a new session for the user in your database.
The verify token examples on the Google+ Github page demonstrate concise code for sending and verifying ID tokens.
Let's discuss the details of one approach to passing a type of bearer token, the ID token, for authentication.
User signs in to your site
The Google+ Sign-In button returns an ID token in a callback
The client securely passes the ID token to the server
The server verifies the ID token*
The client session is then authenticated
The steps for * are best put in another question, however a typical set of tests includes:
Verify the token's certificate is Google's
Verify the client id is for this app
Verify the user has an account on your site (optional, do this if you need offline access)
Verify the token hasn't expired
Hope that clears things up for the two.
There is one final flow you should be aware of, used for offline API access, token refresh. Token refresh happens when you have a refresh token and an expired access token. For Google's implementation of OAuth 2.0, access tokens expire after 3600 seconds (1 hour). Because these tokens expire, you need to be able to get new access tokens when your stored access tokens expire. To do this, you pass three bits to Google:
Refresh token (retrieved from code exchange)
Client ID (retrieved from the Google developer console)
Client secret (again, retrieved from the Google developer console)
These parts are passed to the Google OAuth server and the server will then return a fresh access token that you can use for offline API access.
There's a wealth of information on this topic, see also:
Using the one-time code flow for Google+ Sign-In
Google+ Developer documentation, Token Verification