What's the makeup of my access token from Google? - oauth-2.0

I've acquired the following access token through Google OAuth Playground.
ya29.Ci9aA2EirNhY3InpsLC2Q5ct1XZh2UL60oWWVmkMCBBUL0M-4oAAoigZCJ6O_a4geA
It does not appear to be a JWT (or JWS/JWE for that matter), because I would expect something like 3 segments. The first segment also seems too short to encode the token type.
I know the token must be legitimate, but I cannot for the life of me figure out what specification describes what I'm looking at.
What format is this thing?

The OAuth 2.0 specification says that:
An access token is a string representing an authorization issued to the client. The string is usually opaque to the client.
That is, you should generally not expect to know the format or get any other useful information out of the token.
Of course, it's certainly possible for Google to use JWT or some other container format for the token, but I don't see any indication that that's the case. (This answer also makes me think that they're not in any specified format.)

How exactly are you obtaining that token?
Using the Google's Sign-In button template to initialize the login & grant of permissions process like so gives me a JWT (the idToken):
<meta name="google-signin-client_id" content="{{ OAUTH2_CLIENT_ID }}">
<script src="https://apis.google.com/js/platform.js?onload=onLoad" async defer></script>
<div id="google-signin-button"
class="g-signin2"
data-width="170"
data-height="30"
data-onsuccess="onSignIn"
data-onfailure="onSignInFailure">
</div>
function onSignIn(googleUser) {
var profile = googleUser.getBasicProfile();
var idToken = googleUser.getAuthResponse().id_token;
}

Related

Get Auth0 access token via command line

I am force to use an unergonomic web site (let’s call it zzz) that uses auth0 for authentication, and a REST API internally, and I have a strong desire to use the API directly.
Using the browser inspector, I can see how that API works, and if I use the JWT Access Token (transmitted using Authorization: Bearer) that I find there, I can script access to API.
The problem I am facing is getting such a JWT access token via auth0, given my username and password.
When I use the browser-based login, I see that zzz redirects me to
https://zzz.eu.auth0.com/login
?state=g6…mo
&client=uz…6j
&protocol=oauth2
&response_type=token%20id_token
&redirect_uri=https%3A%2F%2Ffoo.zzz.com%2Fcallback
&scope=openid%20read%3Amore%20scopes…
&audience=zz-api-prod
&nonce=0G…L7
&auth0Client=ey…n0%3D
(line breaks for your convenience)
I can now manually enter username and password, and get logged in, which seems to perform these steps:
A POST to
https://zzz.eu.auth0.com/usernamepassword/login
with a body of
{ "client_id":"uz…6j",
"redirect_uri":"https://foo.zzz.com/callback",
"tenant":"zzz",
"response_type":"token id_token"
"connection":"zzz-production-users",
"username":"…",
"password":"…",
"nonce":"0G…L7",
"state":"g6…mo",
"sso":true,
"_intstate":"deprecated",
"_csrf":"fb…KI",
"audience":"zzz-api-prod",
"auth0Client":"ey…n0=",
"scope":"openid read:stores more:scopes …",
"protocol":"oauth2"
}
and a response of
<form method="post" name="hiddenform" action="https://zzz.eu.auth0.com/login/callback">
<input type="hidden" name="wa" value="wsignin1.0">
<input type="hidden"
name="wresult"
value="ey…tE">
<input type="hidden" name="wctx" value="…">
<noscript>
<p>
Script is disabled. Click Submit to continue.
</p><input type="submit" value="Submit">
</noscript>
</form>
The JS on the login page seems to press that submit button, causing a POST to
https://zzz.eu.auth0.com/login/callback
which redirects to
https://foo.zzz.com/callback
#access_token=ey…7Q
&scope=openid%20read%3Amore%20scopes…
&expires_in=7200
&token_type=Bearer
&state=%7B%7D
&id_token=ey…Sg
… which contains the precious access token that I want.
Trying to script this precise flow, which would involve parsing the returned HTML to extract the wctx and wresult arguments, is quite tedious.
So my question is:
Is there a way to get the access_token some other way that is more convenient to script using just command line curl, or maybe some simple python code/library?
I have tried various things that I found on the auth0 documentation website (e.g. https://auth0.com/docs/api-auth/tutorials/password-grant#realm-support), but could not get them to work; presmably because they need to be explicitly enabled by zzz in their auth0 settings?
The correct approach should be a separation between these:
Unergonomic web site (Client A) - which uses the implicit flow
Web API
Client B (your command line) - which uses a different flow
In Auth0 you should configure a new OAuth Client Entry for Client B, which should probably use a different flow - perhaps the password grant you mention.
You will at least be able to get a token in this manner. Whether the API accepts calls from you may depend on other design aspects.

Cant get simple Oauth wth vertx to work with google

Trying to create a web client that uses oauth to connect to multiple sso endopints, google mainly. This is on top of a spring boot project, I just keep getting the same error that no code is provided, but I'm not sure how i'm supposed to get a code without the access token first. Here is a simple version of what im trying to run I want localhost/8080 to redir to google to login and comeback to the same page or a different one doesn't matter
#RequestMapping("/google")
fun google(#RequestParam(value = "code") code: String?, model: Model): String {
val clientId = "asdf.apps.googleusercontent.com"
val secret = "1234"
var goog = GoogleAuth.create(Vertx.factory.vertx(), clientId, secret)
goog.authenticate(JsonObject().put("code", code), {
System.out.println(it)
})
return "test"
}
the error is always
"error": "invalid_request",
"error_description": "Missing required parameter: code"
}}
e```
but how can I provide a code first I need some sort of response from the server. I'm pretty familiar with restful oauth and must be missing something
You can't use the GoogleAuth like that. GoogleAuth provides the basic primitives to handle the OAuth2 protocol. As you're not using the vertx-web part you will need to setup a callback endpoint in your application (I guess it's the /google endpoint you listed) but now you miss the whole Oauth2 handshake. Your client (browser) should call Google, which calls your server to validate the code.
So what you're asking here is to re-implement the vert.x web Oauth2Handler using Spring Boot APIs.

How do you use an iOS Google ID Token to fetch a user's full profile from the backend (Node JS)?

I'm using the Google Login iOS SDK to login, then passing GIDGoogleUser.authentication.idToken to the server, which I'm then verifying in Node JS. The verification in the code below works fine. "payload" var ends up being correct with basic information about the user.
How do I translate the idToken into credentials that I can use to git the people.get endpoint? (I want to know whether the user is using the default Google profile photo or not, and that is available from the people.get endpoint.) This does not seem to be documented anywhere.
https://developers.google.com/people/api/rest/v1/people/get
var auth = new GoogleAuth;
var client = new auth.OAuth2(GoogleUtils.clientIDs, '', '');
client.verifyIdToken(
token,
GoogleUtils.clientIDs,
// Or, if multiple clients access the backend:
//[CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3],
function(e, login) {
if (e) {
return next(e, null);
}
var payload = login.getPayload();
return next(null, payload);
});
Thanks for your help. I can't seem to find any of this info in the documentation. Google's APIs are very poorly documented it seems.
Unfortunately, as noted, the current ID token payload does not say whether the photo is the default one (probably something we should add). If you need an access token to call Google's REST APIs (such as people.get) for more user data, then you need to obtain an OAuth auth code, and exchange it for access and refresh tokens, as documented at https://developers.google.com/identity/sign-in/ios/offline-access

How to obtain a Google oauth2 refresh token?

The following code uses the Google oauth2 mechanism to sign in a user. We need to process updates to the user's calendar while the user is offline, so we ultimately need the 'refresh token'. Does the result from grantOfflineAccess() return the refresh token (below, I can see that response.code holds a value that might be the refresh token)?
How can I get a refresh token that can be used (server side) to create new access keys for offline access to a user's Google calendar?
<script type="text/javascript">
function handleClientLoad() {
gapi.load('client:auth2', initClient);
}
function initClient() {
gapi.client.init({
apiKey: 'MY_API_KEY',
clientId: 'MY_CLIENT_ID.apps.googleusercontent.com',
discoveryDocs: ['https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest'],
scope: 'https://www.googleapis.com/auth/calendar'
}).then(function () {
var GoogleAuth = gapi.auth2.getAuthInstance();
GoogleAuth.signIn();
GoogleAuth.grantOfflineAccess().then(function (response) {
var refresh_token = response.code;
});
});
}
</script>
<script async defer src="https://apis.google.com/js/api.js"
onload="this.onload=function(){};handleClientLoad()"
onreadystatechange="if (this.readyState === 'complete') this.onload()">
</script>
There is a reason why you are having a problem getting a refresh token out of JavaScript. That reason being that it's not possible.
JavaScript is a client side programming language, for it to work you would have to have your client id and client secret embedded in the code along with the refresh token. This would be visible to anyone who did a view source on the web page.
I think you realize why that's probably a bad idea. The main issue is that gapi won't return it the library just doesn't have that ability (not that I have tried in raw JavaScript to see if the OAuth server would return it if I asked nicely).
You will need to switch to some server side language. I have heard that this can be done with Node.js, but haven't tried myself. And Java, PHP, Python are all valid options too.
Based from this post, you should include the specific scopes in your requests. Your client configuration should have $client->setAccessType("offline"); and $client->setApprovalPrompt("force");.
After allowing access, you will be returned an access code that you can exchange for an access token. The access token returned is the one you need to save in a database. Later on, if the user needs to use the calendar service, you simply use the access token you already saved.
Here's a sample code:
/*
* #$accessToken - json encoded array (access token saved to database)
*/
$client = new Google_Client();
$client->setAuthConfig("client_secret.json");
$client->addScope("https://www.googleapis.com/auth/calendar");
$_SESSION["access_token"] = json_decode($accessToken, true);
$client->setAccessToken($_SESSION['access_token']);
$service = new Google_Service_Calendar($client);
//REST OF THE PROCESS HERE

Google OAuth 2.0 Response

I need help figuring out why my OAuth 2.0 response is always something like:
https://accounts.google.com/o/oauth2/approval?as=[BUNCH OF LETTERS AND NUMBERS]&xsrfsign=[BUNCH OF LETTERS AND NUMBERS]
This is the response after I login to my Google account and click allow access to the application.
It's nothing like the response I'm expecting according to the documentation (http://code.google.com/apis/accounts/docs/OAuth2WebServer.html#handlingtheresponse)
First of all, you did not specified the language you are coding.
Secondly, make sure you specify the corect RedirectUri. You can get or set if from google console (https://code.google.com/apis/console/).
Then, for this kind of url https://accounts.google.com/o/oauth2/approval?as=.....&xsrfsign=..... you won't get the authorization code from the url but from the content of the page:
I have extracted it from the raw code of the page: [C# code]
string []s=webBrowser1.Document.ActiveElement.InnerHtml.Split (new string [] {"value=\"", "\""}, StringSplitOptions.None);
string authCode=s[165];

Resources