Actions on Google account linking without refresh tokens or using 3rd party provider - actions-on-google

The docs for account linking for actions on google say you must provide a refresh token for implicit flow - it doesn't mention if this is required for Authorization code flows. https://developers.google.com/actions/identity/oauth2-implicit-flow
So if I had an end point that produces access tokens but doesn't issue refresh tokens (the access tokens do expire but I require a user to authenticate again in this instance - this is a security requirement outside of my control) can we still use the Authorization Code flow in this instance?
Finally how would this work with 3rd party login providers? So if I offer Facebook Login on my web app then I also won't receive a refresh token. I know I can get an extended Facebook token, but again there's no guarantee a user will use my action whilst that token is valid.
In both cases do we just return a 401 unauthorized error and will this prompt the user to sign in again from a google action side?

Take a look at the Google Assistant Smart Home sample, which uses Authorization codes. When the HomeGraph makes an HTTP request to your cloud, it does so for a particular user. It tries to include a token, but if the token expired, it sends a new request to get the latest access token.

Related

Google Home or Google Assistant Home Control behavior for long inactivity by end user

We have developed a Google Home Action integrating it with Keycloak OAuth and Custom Webhook The OAuth access token from Keycloak has a validity of 15 days
But after a long time of inactivity (1-2 months approx), the Testing Link was disabled and the Google Assistant was replying with the message '{Action Name} is unavailable right now' for all Smart Home Action voice commands like 'Sync my devices'
We have also enabled Testing in the deep link URL for the action test after this
But even after the Test was enabled, it still gave the same error message for all the voice commands.
What is the expected implementation change to be done either from the Webhook or Google Home Action configuration side to handle such cases as the Google Home App is not asking the user for relinking the Action if the access token gets expired in the backend?
The Keycloak URL and access details are configured in Google Action and the redirections to login and handling token are done by Google itself. So it is not in our control to get a new token without relinking the Google Home.
Relinking on Google Home is the only option here or should I increase the Keycloak token validity?
P.S. - Do not close this ticket if a satisfying answer is not received by me. My previous ticket was closed without a proper answer and I had to raise this question again.
The expectation is when an access token expires, Google sends a request to your token exchange endpoint to exchange a refresh token for a new access token.
Check out the Smart Home OAuth docs to make sure that you're endpoint is providing the exchange refresh token info to get access tokens. Below is an example of what your endpoint should return.
{
"token_type": "Bearer",
"access_token": "ACCESS_TOKEN",
"expires_in": SECONDS_TO_EXPIRATION
}
For more information on using tokens, I recommend checking out Google Account Linking, section "Working with tokens"

Sign In With Apple - App Access Token Support?

I'm just looking at migrating an existing Login with Facebook flow over to Sign in with Apple with the hope of eliminating FB Login entirely from our iOS app.
The client side seems straight forward enough, however there's one topic I can't seem to see any documentation or discussion on Stack Overflow about - a Sign In with Apple equivalent for FB App Access Tokens.
Facebook Login supports different token types (https://developers.facebook.com/docs/facebook-login/access-tokens/) and currently our app back end supports 2 authentication flows.
From End App Users, they Login with Facebook, send the provided client User Access Token to the app backend which validates the token against Facebook and then issues an app specific JWT token to the app client that is used in further app API calls until expiry.
From backend server components. These request an App Access Token from Facebook e.g.
curl -X GET "https://graph.facebook.com/oauth/access_token
?client_id={your-app-id}
&client_secret={your-app-secret}
&grant_type=client_credentials"
The App Access Token is then send to the app backend which validates the token against Facebook and then issue an app specific JWT token that is used in further server to server API calls until expiry.
Replacing 1 above seems straightforward but what about 2? Is there a mechanism for achieving the same flow with Sign In with Apple?
It seems like the https://developer.apple.com/documentation/signinwithapplerestapi would be the API to use for validation but is there a way to generate an App Access Token equivalent for Sign In with Apple in the first place to validate using this REST API?
Thanks
I think it's possible
I'm not exactly sure how to really use it or validate it yet, but you get an access_token in the response from https://appleid.apple.com/auth/token when Generating and Validating Tokens
Getting an access_token from Apple
This example assumes you have an Authorization Grant Code, but the same is possible if you have a refresh_token, etc. instead.
Prepare a POST request to https://appleid.apple.com/auth/token
Fill out the following key-values as x-www-form-urlencoded:
client_id
client_secret
code
grant_type
redirect_uri
If successfull, this will return:
**access_token**
token_type
expires_in
id_token
I'm not sure if this is the type of access_token you're looking for, but I wanted to bring it to your attention.
It may be useless for now
After writing this, I came across this thread in the forums where Apple said:
Currently, the access token only indicates a successful refresh token validation. There are currently no endpoints where it can be used and it is reserved for future use. So, it can be ignored for now.

REST API for website which uses Facebook for authentication

We have a website where the only way to login and authenticate yourself with the site is with Facebook (this was not my choice). The first time you login with Facebook, an account gets automatically created for you.
We now want to create an iPhone application for our site and also a public API for others to use our service.
This question is about how to authenticate with our website from the app/API and is broken into 2 parts:
What is the correct way to handle REST authentication from an API to a website which only uses Facebook OAuth as an authentication method?
I have read and researched a lot about standard methods of authentication for REST API. We can't use such methods as Basic Auth over HTTPS, as there are no credentials for a user as such. Something like this seems to be only for authenticating applications using the API.
Currently, the best way I can think is you hit an /authorize end-point on our API, it redirects to Facebook OAuth, then redirects back to the site and provides a 'token' which the user of the API can use to authenticate subsequent requests.
For an official application that we create, we wouldn't necessarily need to use the public API in the same way. What would be the best way then to talk to our website and authenticate users?
I understand (I think) how to authenticate 3rd-party applications that are using our API, using API (public) keys and secret (private) keys. However, when it comes to authenticating the user who is using the app, I am getting rather confused about how to go about it when the only way we have to authenticate a user is Facebook.
I feel like I'm missing something very obvious, or don't fully understand how public REST APIs should work, so any advice and help would be greatly appreciated.
UPDATE: see below
I've been thinking hard about this question too. It's not entirely clear to me yet but here's the route I am thinking of going. I am creating a REST API an my users only auth with Facebook connect.
On the CLIENT:
Use the Facebook API to login and get an OAUTH2 code.
Exchange this code for an access token.
In every call to my custom API I'll include the Facebook user id and the access token.
On the API (for every method that requires user authentication):
Make a request to the /me Facebook graph using the access token from above.
Verify that the Facebook user id returned matches the user id passed to my API from above.
If the access token has expired additional communication is required.
I have yet to test this. How does it sound?
--- Update: July 27th, 2014 to answer question ---
I only use the above exchange once upon login. Once I determine which user is logging in, I create my own access token, and that token is used from that point going forward. So the new flow looks like this...
On the CLIENT:
Use the Facebook API to login and get an OAUTH2 code.
Exchange this code for an access token.
Request an access token from my API, including the Facebook token as a parameter
On the API
Receive access token request.
Make a request to the /me Facebook graph using the facebook access token
Verify that the Facebook user exists and match to a user in my database
Create my own access token, save it and return it to the client to be used from this point forward
This is my implementation using JWTs (JSON Web Tokens), basically similar to Chris' updated answer. I have used Facebook JS SDK and JWT.
Here's my implementation.
Client: Use Facebook JS SDK to log in and get the access token.
Client: Request JWT from my API by calling /verify-access-token endpoint.
MyAPI: Receives access token, verify it by calling /me endpoint of Facebook API.
MyAPI: If access token is valid, finds the user from database, logs in the user if exist. Create a JWT with required fields as payload, set an expiry, sign with the secret key and send back to the client.
Client: Stores the JWT in local storage.
Client: Sends the token (the JWT from step 5) along with the request for the next API call.
MyAPI: validate the token with the secret key, if token is valid, exchange the token for a new one, send it back to the client along with the API response. (No external API calls for verification of the token here after) [if the token is invalid/expired request client to authenticate again and repeat from 1]
Client Replaces the stored token with the new one and use it for the next API call. Once the token expiry is met, the token expires revoking access to API.
Every token is used once.
Read more answers about security and JWT
How secure is JWT
If you can decode JWT how are they secure?
JSON Web Tokens (JWT) as user identification and authentication tokens
I am trying to answer the same question and have been going through a lot of reading recently...
I won't have "the" answer but things are getting a little clearer for me. Have you read the comments in the article you mentioned? I found them really interesting and helpful.
As a result, and in the light of how things have evolved since the first article has been written, here's what I think I'll do:
HTTPS everywhere — this allows you to forget about HMAC, signing, nonce, ...
Use OAuth2:
When authentication requests come from my own apps/website, use this 'trick' (or a variation of it) described in a reply to the article mentioned before.
In my case, I have two types of users: those with classic login/password credentials and those who have signed up with Facebook Connect.
So I'd provide a regular login form with a "Login with Facebook" button. If the user logs in with his "classic" credentials, I'd just send these to my OAuth2 endpoint with a grant_type=password.
If he chooses to log in via Facebook, I think that would be a two-steps process:
First, use Facebook iOS SDK to open an FBSession
When that's done and the app is given back control, there should be a way to get a Facebook ID for that user. I'd send this ID alone to my OAuth2 endpoint with an extension grant understood by my server as "using an FB User ID".
Please note that I am still heavily researching on all this stuff, so that might not be a perfect answer... maybe not even a correct one! But I think that would make for a good starting point.
The idea of using an "extension grant" for the Facebook authentication might involve having to register it to do things properly? I'm not quite sure.
Anyway, I hope I was able to help you even a bit, and that at least it can start a discussion to find the best solution to this problem :)
Update
The Facebook login is not a solution as pointed in the comments: anybody could send an arbitrary user ID and log in as this user on the API.
What about doing it like this:
Show a login form with a "Facebook login" button
If this login method is chosen, act kinda like the Facebook SDK: open a web page from your authentication server, which will initiate the Facebook login.
Once the user has logged in, Facebook will use your redirect URL to confirm; make that URL point to another endpoint of your authentication server (possibly with an extra parameter indicating the call came from an app?)
When the authentication endpoint is hit, the authentication can securely identify the user, retain its FB User ID/FB Session and return an access token to your app using a custom URL scheme, just like the Facebook SDK would do
Looks better?

Google Account access token

How to extend life time of google account access token i used gwt-oauth2-0.2 to obtain an access token but problem is that it expires very soon .i want to get a token with extended life time preferably that does not expires.
Since this is GWT code, it's executed in the client using client-side JavaScript. It is not possible to get a long-lived access token from within client-side JavaScript. The issued tokens last 60 minutes currently-- and you can always get another token later without any user interaction (as the user has already approved the OAuth grant request). This should be sufficient for all client-side access to a user's data.
If you're comfortable using server-side code instead, you could use the OAuth 2.0 flow for server-side web applications, and specify access_type=offline. This gives you an authorization code passed as a query parameter-- you then make a server-to-server call to exchange the authorization code for an access token. The first time you exchange a code for a given user, you'll also get a refresh token. Although the access token will expire, the refresh token can be used indefinitely to obtain new access tokens for that user by simply making a server-to-server call.

When I should load a new access token?

My app uses Facebook Javascript SDK authorization on client side, and for authorized user app fetches access token from Facebook API, using facebook cookie with signed request and provided code, and store it into database.
Everything is working fine, but i'm wondering, when I should refresh stored access token? What if user have changes password, and have signed in/connected again.
As I understand, now she has new access token, and app should load it from Facebook. But how I can understand when I should check for a new token? Check on each request with facebook cookie doesn't work, because it's few request per second for each user (event if she didn't change a password). Or maybe i'm doing something wrong?
I mean:
I've authorized user on client side
I've cookie with signed request
Signed request is pretty enough to authorize user on server side (validate user credentials)
I can get access token by calling Facebook API, anytime when user user makes request to my app (because I need a code from signed request). So, i'm doing it when I don't have stored access token or existing access token has expired.
access token just stored in database, and can be used anytime, in different thread, maybe few minutes later (mean we don't have user request and cookie with signed request)
What if stored access token not expired, but invalidated on facebook side? I need to fetch new access token, but cookie has gone at this moment.
Currently I see only one way: store code from signed request into databse, and when we have found that we have invalid access token, try to load it. But i'm note sure that it's proper way, and not so much usable for most cases
You have client token and server token, the client one is short lived (a few hours) and the server one is long lived (60 days).
The token on the client side should not bother you too much since you can get a new one easily as it states in the "Handling Invalid and Expired Access Tokens" guide:
Desktop Web and Mobile Web apps which implement authentication with the Javascript SDK
Calling FB.getLoginStatus() or ensuring status: true is set when you
call FB.init() means that the next time a user lands on your
application and is signed into Facebook, the authResponse object you
are passed as a result of those calls will contain a fresh, valid
access token.
In this case, its simply the act of the user using your application
which implicitly generates a new access token.
The token on the server side, which you persist in the db, can not be as easily reproduced, the user has to be sent to the auth dialog again:
Desktop Web and Mobile Web apps which implement the server-side authentication flow
To obtain a fresh access token in this case you must pass the user
through the full server-side flow again: i.e. obtain a code and
exchange it for a new access token.
However, assuming the user has not de-authorized your application,
when you redirect the user into the OAuth Dialog, the user will not be
prompted to reauthorize your application, and will be immediately
redirected to your redirect_uri. This means that the re-authentication
process can appear transparent to the user.
You can of course send a client token to the server and persist that, but it's pretty pointless since it's short lived.
Another option is to use the new endpoint to extend a valid client token on the server side and then persisting that.
As for "how to know when do get a new token", on the server side when you are making api requests just check the response and see if an error returned and if so what it is (there's a list in the first url I added).
If the token has expired then just send the user to the auth dialog again (you can return some kind of code to the client side and do it from there) and then save the new token to the db.
There's no need to check cookies, those are used in the background but you should not have anything to do with them.
Edit
Don't use the cookies, they should not concern you at any time.
What you should do:
On the server side you should follow the instructions in the Server-Side auth guide, get the "code" and exchange it with a token.
That token will have 60 days.
Use that token, which you store in your db, as needed (other threads, what not) and when you are getting an error back from facebook saying that the token has expires just navigate the user back to the auth dialog page.
You can not use the "code" to get more than one token so that won't help you.
If the user session (and token) got invalidated (for various reasons) you will still get an error back from facebook when trying to make an api request, when that happens just send the user to the auth dialog again.