Passing Google access token from client to server - google-cloud-platform

I have an application integrated with Google services (Google Bigquery API to be specific.)
I am authenticating the user on the client side, without offline access scopes (hence without refresh tokens), and doing most of the operations on the client side. But there are some operations I want to do on the server side (still on the authenticated user's behalf.)
Currently, I am passing access tokens to the server side (over https), initializing Google libraries on the server side with this token, and doing the operations there.
The documentations I've found on Google regarding this are either using authentication on the server side, with refresh tokens or completely on the client side. Could not find a documentation suggesting best practices for this mixed case.
In short, what I want to do is, using short lived access tokens acquired on the client side on the backend.
Are there any security risks with this approach? And regardless of that, is this the suggested way of doing what I want?

Regardless of BigQuery oAuth2 implementation, the market general security best practice is to store ONLY short term Security Token on the client side. Even that might be a challenge depending on your client security technique and framework.
Two important points from the official OAuth 2.0 Authorization Framework: Bearer Token Usage
Token storage
Don't store bearer tokens in cookies: Implementations MUST NOT store
bearer tokens within cookies that can be sent in the clear (which
is the default transmission mode for cookies). Implementations
that do store bearer tokens in cookies MUST take precautions
against cross-site request forgery.
Short Term Token
Issue short-lived bearer tokens: Token servers SHOULD issue
short-lived (one hour or less) bearer tokens, particularly when
issuing tokens to clients that run within a web browser or other
environments where information leakage may occur. Using
short-lived bearer tokens can reduce the impact of them being
leaked.
Now checking Bigquery documentation in this link
Their recommendation is: Save refresh tokens in secure long-term storage which are typically not done on client side storage framework.
Since you always get a refresh Token from BigQuery oAuth2 API you can use it on all your API call, done on the server side, thus giving the user a seamless secure flow. Check this in google oauthplayground
BTW: Typically doing call from the client side is for performance reasons, In BigQuery case since it's a big data solution I feel the extra few seconds involve in server-side calls are less important

Related

Why is BFF pattern deemed safer for SPA's?

I am designing a new web application which requires an oAuth2 implementation. I've been reading up on oAuth2 Authorization Code flow with PKCE. That makes sense, it ensures that de client who is initiating the Authorization Code flow is the same client as the one who is exchanging the authorization code for access token (and/or refresh token).
But then I was wondering on how we could deal with refresh tokens. I understand that BFF is now the preferred solution for this, where we use a separate component (Backend for Frontend) that handles all calls from the web app and proxies those to the backend api, all the while handling all access tokens and refresh tokens. The web app and BFF maintain a session cookie, so the BFF can track which access token should be added to which request and so forth.
Most blogs mention something in the lines of "and this is safe if you set the session cookie to strict and http only and secure, because no malicious JS can get that cookie then".
And that is where I have trouble understanding why this is safer. If cookies are safe enough to deal with session id's, then why are they not safe enough to deal with access tokens? Or even refresh tokens? If they are cookie based, then they are sent with each request and no malicious JS can access it. If they could, then the BFF model doesn't provide any additional security, just a little more complexity, no?
So bottomline is: if BFF is deemed safe(r) because the sessions are kept in secure http-only cookies, why is keeping access/refresh tokens in secure http-only cookies not safe?
Adding a BFF to the mix does change the security of using tokens. The BFF is a confidential client so it makes the whole solution more secure, for sure, but this is not the only reason you would use a BFF. One of the main benefits is to keep tokens away from the browser. You don't want the tokens to be accessible by Javascript, that's why you want to rely on cookie-based sessions instead. This protects you from XSS attacks that want to steal the tokens. However, using sessions opens you to CSRF attacks and session-riding attacks. Protecting against CSRF and session-riding should be a bit easier than mitigating XSS as you can become vulnerable to XSS through a third-party library's dependency, for example.
E.g. in case of BFF: steal session from cookie -> make request to BFF -> get access to user data. In case of no BFF: steal AT/RT from cookie -> make request to API -> get access to user data. I still don't understand how this is safer, I am sorry for not understanding it.
You don't have to be sorry! It's good that you're trying to understand that.
The problem with your example is this: you assume that there is no BFF, but AT/RT are kept in cookies. If you're using cookies then it means that you have some sort of a backend component that sits between your SPA and APIs. Otherwise, you would have to deal with tokens in the browser (readable by JS). So the difference that you should be contemplating here is — am I using HTTP-only cookies to call my APIs or do I need tokens and set Authorization headers in JS? For the former case, it doesn't matter if you have a session ID in the cookie or the actual AT. The important part is that JS can't read the content of that cookie.
Another thing is that it's harder to steal sessions than tokens kept in JS. For someone to steal data from cookies you would need a Man-in-the-browser attack. If the tokens are available to JS, then all you need is an XSS attack to steal them.
As I mentioned, using cookies opens you up to CSRF and session-riding attacks, but their impact is limited:
the attacker can only perform an attack when the user has an open session. As soon as the user closes the browser no more data can be stolen (whereas, when an attacker steals a token, they can read data for as long as the token is valid)
the attacker can only perform the same actions that a user can from the front end. This should also be the case for a stolen AT, but in reality, access tokens usually have too broad privileges, and there are APIs you can call with a token that are not normally accessible from the UI.
At Curity we have spent some time researching this and you can have a look at this whitepaper we wrote about the security of SPAs and the pros and cons of different approaches: https://curity.io/resources/documents/single-page-application-security-whitepaper
BFF is considered safer not because of the cookie usage when using the access tokens but because the way of obtaining tokens is more secure. SPAs by definition are not able to keep a secret (in the browser) thus have to use a flow that involves a public client. The BFF allows for a confidential client because the client secret is kept in the backend.
Using PKCE with the public client gives you assurance indeed about the same entity requesting and receiving the tokens, but it give you little assurance about the authenticity of that client. A confidential client takes care of the latter.

How can I protect refresh_token which generated by AWS Cognito for Single Page Application

I am planning to create a single page web application and all user authentication would be handled by AWS Cognito. By reading through some of articals, they all suggest using "code" grant flow + PKCE rather than implicit flow since implicit flow is deprecated in OAuth 2.1
I created a test user pool with AWS Cognito, by using Postman I successfully get access_token, id token and refresh token with code grant flow + PKCE.
I double checked with AWS Cognito Doc, seems refresh token will always be returned if using code grant flow and I cannot find anywhere in AWS console to disable returning refresh token. So just wondering how can I protect refresh_token? Cookie or localStorage can not stop XSS.
It is usual to route requests for tokens via a backend, eg a utility API, which also represents the refresh token as an HTTP Only SameSite=strict encrypted secure cookie. See this crypto code for an example.
The backend component also enables you to use a client secret, in addition to PKCE, which improves security a little. Cognito supports this, so I'd recommend using both.
BEST PRACTICE
OAuth for browser based apps recommends this approach. Stakeholders often expect you to be using the backend for frontend described, and it will make life more comfortable if you have to explain your app's security.
XSS
With the above HTTP only cookie approach, malicious code would not be able to steal your refresh tokens, and this is therefore the recommended way to handle them.
If your SPA has XSS vulnerabilities, then malicious code might be able to steal your data though, regardless of whether tokens or cookies are used to access data. Therefore it is critical to implement XSS protection carefully, regardless of your OAuth solution.

How to get my own Google API access token without using "Log in with Google"?

On my site, I want to be able to retrieve whether my own YouTube account goes live. After looking around, I found this endpoint:
GET https://www.googleapis.com/youtube/v3/liveBroadcasts,
that would help me do just that. However, the main problem I found is that it requires an OAuth2 token, and the only way I could find to generate one was going through the whole Login with Google approach.
My main problem is that I want anyone who visits my site, to be able to see whether I'm live or not. I'm not looking for workarounds or using web crawlers either - I want to be able to use this specific endpoint. Is that even possible?
In other words, is it possible to get my own access token manually, and just plug that into the API request to access the endpoint directly? Or is this just impossible?
First thing to know about YouTube Data API is the following: for to issue authorized request to it, one cannot alleviate authentication through the browser.
You may read the doc OAuth 2.0 Flow: Installed apps for thorough info about the authorization flow on standalone computers.
The doc specifies step 4 -- Handle response from Google -- and step 5 -- Exchange authorization code for refresh and access tokens. By the initial OAuth flow, you get two tokens: a short-lived access token and a refresh token that produces access tokens on demand. Authentication without browser is not possible, but once having a refresh token, it can be traded programmatically for access tokens:
Initialization: obtain via browser authentication a refresh token;
Iterations: as many times as needed, query the API for an access token -- without any browser interaction! -- using the refresh token from (1), then proceed further with the call to the target API endpoint (again, without any browser interaction).
Note that the steps (1) and (2) may well be separated such that (1) is executed by a standalone (local) computer that stores the refresh token into a file; later, upon a secure transfer of that file on a different remote computer (e.g. a server that does not have a browser installed), execute (2) on that remote computer, repeatedly as needed
(see Using OAuth 2.0 for server-side, standalone scripts.)
Sounds right:
complete the flow (once) with your own google account,
cache the token server-side, and
include the API’s response when serving your page.
Pitfalls:
How long are OAuth tokens valid for? (The API will start returning errors if this occurs)
How often will the page be generated vs. what rate-limits does the API have? ( you may have to request status at most once per few minutes, and cache the response)

JSON Web Token expiration and remember me functionality

I am starting to work on an authentication system for an angular 2 Single Page Application using django-rest framework as back-end. I'd also like to have some kind of "remember me" functionality that is going to keep users logged in for a certain amount of time.
From what I have read so far, it seems that the best authentication method for this kind of Angular 2 SPA/REST API is using jwt (json web token). For jwt authentication, I looked at the django-rest-framework-jwt (https://github.com/GetBlimp/django-rest-framework-jwt).
The problem that I see is that the token needs to have a short life span (few minutes to a few hours...) in order to minimize security issues if the token get stolen. The token now needs to be refreshed frequently to avoid the user from being disconnected while using the application. In this case, a "remember me" functionality is posing problem since the token have a short life span.
I thought about a solution involving a second token that would serve as a refresh token. It would be opaque, have a longer life span and would contain information specific to the user (ip address or something like that) so that if it get stolen, the information specific to the user being different would render this refresh token invalid.
So here are my questions:
1- I would like to know if they are existing solutions addressing this problem. As any security/authentication issues, I prefer to rely on well tested solutions to avoid getting my API compromised.
2- Would the refresh token based on specific user infos be a good idea?
3- Any other ideas how I could implement what I want?
For your situation, you really need a way to store issued tokens.
I always use an OAuth2.0 server setup that manages the auth and returns tokens the OAuth setup uses a database to manage everything so it's easy to manage and revoke tokens.
The database schema would be like this http://imgur.com/a/oRbP2 the problem with using just JWT without any management over the issued tokens with long expiration you have that security issue of not being able to revoke easily.
I would advise against including any such thing as a password in the JWT and requiring them to change it what if they use that password everywhere, then they would have to change that everywhere.
Updated from comments
Sessions Authentication use session_id which most the time is stored in a cookie and this is attached to every outgoing request. It is stateful. It is nothing more than a unique identifier that associates a user account that the server has in memory/database. For example, this can course problems when running multiple servers/instances when scaling your infrastructure.
Token Authentication no session is persisted on the server so this means it is stateless. It normally uses the header Authorization: Bearer REPLACE-WITH-TOKEN . This means that this token can be passed to multiple different servers/instances because the authentication is not limited to the server that you initiated the authentication on. This helps with scaling your infrastructure. Tokens can also be passed to other clients.
RESTful API's are stateless so there must not be a session state stored on the server. Instead, it must the handled entirely by the client so that's why token authentication is used.
I had the exact problem when trying to use JWT with an application that needed a lot more than JWT was designed for. OAuth2.0 has a lot more options that I believe are necessary to meet your requirement in the safest manner possible and even features that you may find very useful in the future as your Application may grow and need more features with regards authentication.

OAuth v2 communication between authentication and resource server

I'm having some troubles understanding how OAUTH-v2 works.
The OAuth version 2 spec reads:
Accessing Protected Resources
The client accesses protected
resources by presenting the access
token to the resource server. The
resource server MUST validate the
access token and ensure it has not
expired and that its scope covers
the requested resource. The methods
used by the resource server to
validate the access token (as well as
any error responses) are beyond the
scope of this specification, but
generally involve an interaction or
coordination between the resource
server and the authorization
server.
How does this interaction between resource server and authorization server work in practice?
How does the resource server
determine that an access token it
received is valid?
How does the
resource server extract the allowed
scope from the token to see if access should be granted to a particular resource? Is the Scope encoded in the access token, or does the resource server first have to contact the authorization server?
How is trust between the resource server and the authorization server established?
Access token attributes and the
methods used to access protected
resources are beyond the scope of this
specification and are defined by
companion specifications.
Can someone give examples for token attributes?
The reason this is out of scope for the specification is the wide range of ways to accomplish this connection between the two entities. The main question is how complex is your deployment.
For example, do you have one server managing authentication and access, and a set of discrete services each with its own servers serving the API calls? Or, do you have just one box with one web server which handles both authentication/authorization and the API calls?
In the case of a single box, not much is needed as the entity issuing tokens is the same as the one validating them. You can implement tokens to use a database table key and lookup the record in the database (or memory cache) on every request, or you can encode the scope, user id and other information directly into the token and encrypt it using a symmetric or asymmetric algorithm.
Things get a bit more complex when dealing with a distributed environment, but not by much. You still issue tokens at the authorization server, but the resource server needs a way to validate those. It can do it by making an internal API available to the resource server to ask the authorization server to "resolve" the token (which can be fast in a local environment), or the two can establish a public/private key pair or symmetric secret and use that to encrypt everything the resource server needs into the token.
Self contained tokens are longer but offer much better performance per-request. However, they come with a price - you can't really revoke them while they are still valid (not expired). For this reason, self contained tokens should be very short lived (whatever is acceptable to you to leave access open after it was revoked - e.g. many sites use one hour), with a refresh token good for a year or more to get new tokens.
One example of resource- to authorization server API is the one at Google Developers Website.
It doesn't specify the format of the access token though, but the response seems pretty universally useful.