Incremental Google OAuth2 — adding new scopes to old tokens - google-oauth

We're running a web service that's been using OAuth2 Login for Google Accounts for the past 10 months.
I'm wondering if there are any known or potential issues when using the new incremental auth for adding new scopes to old tokens, e.g. tokens that were granted up to several months ago?
We're running into a problem that's been verified by two of our devs, but is hard to reproduce since we only have so many accounts with old refresh tokens in a non-production environment. See below for the full story. I'd be curious to hear from anyone at Google whether this may be a bug, or more likely something we're doing wrong on our side.
We were excited to see the new incremental auth, since we're just about to launch a new feature that involves accessing a user's Google Contacts, but only for a specific use case.
So we added a new OAuth endpoint on our server that includes the include_granted_scopes flag and requests only the Contacts scope:
my $url = URI->new('https://accounts.google.com/o/oauth2/auth');
my $params = {
state => 'code_request_contacts',
response_type => 'code',
client_id => $config->{oauth_client_id},
redirect_uri => $c->host . '/auth/oauth',
scope => 'https://www.google.com/m8/feeds',
access_type => 'offline',
approval_prompt => 'force',
include_granted_scopes => 'true'
};
When testing on our local dev machines this worked beautifully: contacts access was granted, and the same token would work for both contacts and the existing scopes (which included userinfo.profile, userinfo.email, and drive.file).
However, when we started testing on our pre-production server which had existing access tokens and Google Accounts connected, we ran into problems: once the contacts authorization completed, the returned tokens would work ONLY for contacts, failing with a "403 insufficientPermissions" when used to make any Drive API requests.
After seeing those errors, we tried (a) revoking access via the Account Permissions page (https://security.google.com/settings/security/permissions), (b) logging out of our app, and (c) logging in again to get a fresh token with the basic scopes. Strangely, at this point the incremental auth for contacts would work like a charm, and the new tokens had all combined scopes as expected.
So this is where are now — we've twice seen a problem that would be a show-stopper for rolling this out to production, but we can't reliably reproduce if its behavior involves old tokens.
Our current workaround is to have the Contacts OAuth request also include all of our initials scopes. This leads to a longer list of warnings when the Contacts popup appears, but it otherwise seems to achieve the desired end result.

Could it be that you have another difference in the new code, e.g., using a different client_id from the one used in the old tokens?

Related

Is it okay to use Firebase Auth SDK for Mobile app authentication on the frontend? [duplicate]

The Firebase Web-App guide states I should put the given apiKey in my Html to initialize Firebase:
// TODO: Replace with your project's customized code snippet
<script src="https://www.gstatic.com/firebasejs/3.0.2/firebase.js"></script>
<script>
// Initialize Firebase
var config = {
apiKey: '<your-api-key>',
authDomain: '<your-auth-domain>',
databaseURL: '<your-database-url>',
storageBucket: '<your-storage-bucket>'
};
firebase.initializeApp(config);
</script>
By doing so, the apiKey is exposed to every visitor.
What is the purpose of that key and is it really meant to be public?
The apiKey in this configuration snippet just identifies your Firebase project on the Google servers. It is not a security risk for someone to know it. In fact, it is necessary for them to know it, in order for them to interact with your Firebase project. This same configuration data is also included in every iOS and Android app that uses Firebase as its backend.
In that sense it is very similar to the database URL that identifies the back-end database associated with your project in the same snippet: https://<app-id>.firebaseio.com. See this question on why this is not a security risk: How to restrict Firebase data modification?, including the use of Firebase's server side security rules to ensure only authorized users can access the backend services.
If you want to learn how to secure all data access to your Firebase backend services is authorized, read up on the documentation on Firebase security rules. These rules control access to file storage and database access, and are enforced on the Firebase servers. So no matter if it's your code, or somebody else's code that uses you configuration data, it can only do what the security rules allow it to do.
For another explanation of what Firebase uses these values for, and for which of them you can set quotas, see the Firebase documentation on using and managing API keys.
If you'd like to reduce the risk of committing this configuration data to version control, consider using the SDK auto-configuration of Firebase Hosting. While the keys will still end up in the browser in the same format, they won't be hard-coded into your code anymore with that.
Update (May 2021): Thanks to the new feature called Firebase App Check, it is now actually possible to limit access to the backend services in your Firebase project to only those coming from iOS, Android and Web apps that are registered in that specific project.
You'll typically want to combine this with the user authentication based security described above, so that you have another shield against abusive users that do use your app.
By combining App Check with security rules you have both broad protection against abuse, and fine gained control over what data each user can access, while still allowing direct access to the database from your client-side application code.
Building on the answers of prufrofro and Frank van Puffelen here, I put together this setup that doesn't prevent scraping, but can make it slightly harder to use your API key.
Warning: To get your data, even with this method, one can for example simply open the JS console in Chrome and type:
firebase.database().ref("/get/all/the/data").once("value", function (data) {
console.log(data.val());
});
Only the database security rules can protect your data.
Nevertheless, I restricted my production API key use to my domain name like this:
https://console.developers.google.com/apis
Select your Firebase project
Credentials
Under API keys, pick your Browser key. It should look like this: "Browser key (auto created by Google Service)"
In "Accept requests from these
HTTP referrers (web sites)", add the URL of your app (exemple: projectname.firebaseapp.com/* )
Now the app will only work on this specific domain name. So I created another API Key that will be private for localhost developement.
Click Create credentials > API Key
By default, as mentioned by Emmanuel Campos, Firebase only whitelists localhost and your Firebase hosting domain.
In order to make sure I don't publish the wrong API key by mistake, I use one of the following methods to automatically use the more restricted one in production.
Setup for Create-React-App
In /env.development:
REACT_APP_API_KEY=###dev-key###
In /env.production:
REACT_APP_API_KEY=###public-key###
In /src/index.js
const firebaseConfig = {
apiKey: process.env.REACT_APP_API_KEY,
// ...
};
I am not convinced to expose security/config keys to client. I would not call it secure, not because some one can steal all private information from first day, because someone can make excessive request, and drain your quota and make you owe to Google a lot of money.
You need to think about many concepts from restricting people not to access where they are not supposed to be, DOS attacks etc.
I would more prefer the client first will hit to your web server, there you put what ever first hand firewall, captcha , cloudflare, custom security in between the client and server, or between server and firebase and you are good to go. At least you can first stop suspect activity before it reaches to firebase. You will have much more flexibility.
I only see one good usage scenario for using client based config for internal usages. For example, you have internal domain, and you are pretty sure outsiders cannot access there, so you can setup environment like browser -> firebase type.
The API key exposure creates a vulnerability when user/password sign up is enabled. There is an open API endpoint that takes the API key and allows anyone to create a new user account. They then can use this new account to log in to your Firebase Auth protected app or use the SDK to auth with user/pass and run queries.
I've reported this to Google but they say it's working as intended.
If you can't disable user/password accounts you should do the following:
Create a cloud function to auto disable new users onCreate and create a new DB entry to manage their access.
Ex: MyUsers/{userId}/Access: 0
exports.addUser = functions.auth.user().onCreate(onAddUser);
exports.deleteUser = functions.auth.user().onDelete(onDeleteUser);
Update your rules to only allow reads for users with access > 1.
On the off chance the listener function doesn't disable the account fast enough then the read rules will prevent them from reading any data.
I believe once database rules are written accurately, it will be enough to protect your data. Moreover, there are guidelines that one can follow to structure your database accordingly. For example, making a UID node under users, and putting all under information under it. After that, you will need to implement a simple database rule as below
"rules": {
"users": {
"$uid": {
".read": "auth != null && auth.uid == $uid",
".write": "auth != null && auth.uid == $uid"
}
}
}
}
No other user will be able to read other users' data, moreover, domain policy will restrict requests coming from other domains.
One can read more about it on
Firebase Security rules
While the original question was answered (that the api key can be exposed - the protection of the data must be set from the DB rulles), I was also looking for a solution to restrict the access to specific parts of the DB.
So after reading this and some personal research about the possibilities, I came up with a slightly different approach to restrict data usage for unauthorised users:
I save my users in my DB too, under the same uid (and save the profile data in there). So i just set the db rules like this:
".read": "auth != null && root.child('/userdata/'+auth.uid+'/userRole').exists()",
".write": "auth != null && root.child('/userdata/'+auth.uid+'/userRole').exists()"
This way only a previous saved user can add new users in the DB so there is no way anyone without an account can do operations on DB.
Also adding new users is posible only if the user has a special role and edit only by admin or by that user itself (something like this):
"userdata": {
"$userId": {
".write": "$userId === auth.uid || root.child('/userdata/'+auth.uid+'/userRole').val() === 'superadmin'",
...
EXPOSURE OF API KEYS ISN'T A SECURITY RISK BUT ANYONE CAN PUT YOUR CREDENTIALS ON THEIR SITE.
Open api keys leads to attacks that can use a lot resources at firebase that will definitely cost your hard money.
You can always restrict you firebase project keys to domains / IP's.
https://console.cloud.google.com/apis/credentials/key
select your project Id and key and restrict it to Your Android/iOs/web App.
It is oky to include them, and special care is required only for Firebase ML or when using Firebase Authentication
API keys for Firebase are different from typical API keys:
Unlike how API keys are typically used, API keys for Firebase services are not used to control access to backend resources; that can only be done with Firebase Security Rules. Usually, you need to fastidiously guard API keys (for example, by using a vault service or setting the keys as environment variables); however, API keys for Firebase services are ok to include in code or checked-in config files.
Although API keys for Firebase services are safe to include in code, there are a few specific cases when you should enforce limits for your API key; for example, if you're using Firebase ML or using Firebase Authentication with the email/password sign-in method. Learn more about these cases later on this page.
For more informations, check the offical docs
I am making a blog website on github pages. I got an idea to embbed comments in the end of every blog page. I understand how firebase get and gives you data.
I have tested many times with project and even using console. I am totally disagree the saying vlit is vulnerable.
Believe me there is no issue of showing your api key publically if you have followed privacy steps recommend by firebase.
Go to https://console.developers.google.com/apis
and perfrom a security steup.
You should not expose this info. in public, specially api keys.
It may lead to a privacy leak.
Before making the website public you should hide it. You can do it in 2 or more ways
Complex coding/hiding
Simply put firebase SDK codes at bottom of your website or app thus firebase automatically does all works. you don't need to put API keys anywhere

Trello OAuth only working with one Google Apps Script

Background
I am able to create Trello cards from Google Apps Script via the
Trello API using the OAuth 1.0 library. The principle is proven/code
works.
I have two distinct Google Apps Scripts projects that need to be able to create Trello cards.
The code in the two different Apps Scripts/Projects is identical - including the same API key/secret.
Only one Apps Script will create a Trello card. This is my problem.
If I reauthorise the other Apps Script, that script will work and the other will give me an API return of "invalid token" and vise-versa. Only one works at a time, but I need both to work.
My thoughts
I think that Trello, via OAuth, see each Apps Script is its own distinct project.
I think that because of this it won't let both apps use the same API key/secret to work with my Trello account. Only one project appears to be able to use the key/secret.
If this is the case I don't know how to make each Apps Script its own project for the Trello API to work for both simultaneously.
Help needed
Does anyone know how to make this work? I need both scripts to be able to create Trello cards. I have a feeling that each apps needs to identify itself uniquely, but I honestly have no idea.
This is really an OAuth logic issue, it's a feature, not a bug. In OAuth, your application exchanges refresh tokens for access tokens. The access tokens only have a limited life span.
When you use a refresh token to generate a new access token, you also get a new unique refresh token and your script stores this for future use, the old refresh token is no longer valid. Similarly, when you re-authorize the application, you get fresh tokens, and any previously generated tokens are rendered invalid.
So when you authorise one script using the same Client ID and Client secret as the other script, you get a new access token and refresh token, and the old credentials, stored by the other script, become invalid.
As a result, the other script can no longer exchange the refresh token it has stored for new access tokens, and it no longer works. Once you re-authorize this copy, the refresh token and access token in the other copy are invalidated in the same way. So you end up going in circles.
You have two options:
Set up a separate OAuth Client (with different Client ID and Client Secret) for each script.
Modify your scripts to use the same storage location for the OAuth Access Token and Secret.
The first approach is going to give you the most reliable consistent results. If you try the second approach, you could still have cases where the scripts run at the exact same time, and one has valid tokens while the other tries to use the now invalid ones. (race conditions).

Restricting Azure Identity Providers

I have set up authentication for my application using the Azure Rest API / OAuth 2 flow, following the steps outlined here:
https://ahmetalpbalkan.com/blog/azure-rest-api-with-oauth2/
I have created an ActiveDirectory application within Azure which is linked to an ActiveDirectory instance.
Inside my own application I have configured it to post to the following Azure OAuth endpoint:
https://login.windows.net/<<MY-AD-TENANT-ID>>/oauth2/authorize?client_id=<<GUID>>&response_type=code
This all works fine. I can authenticate against my ActiveDirectory using emails of the form
someuser#<myDomain>.com
However, I have realised that I can also authenticate using any valid microsoft email address, which obviously means that anyone with a valid microsoft email can get an access token for my application e.g.
randomUser#hotmail.com
Can anyone tell me how I can restrict the authentication to just allow users who are in my Active directory? Users with emails of the form
someuser#<myDomain>.com
I have looked through the documentation but have had no luck so far.
Mechanics of Token Validation
What does that really mean: to validate a token? It boils down to three things, really:
Verify that it is well-formed
Verify that it is coming from the intended authority
Verify that it is meant for the current application
Your problem is that you are not doing the number 3 validation.
You probably are missing something like this in your application where you are validating the token:
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Audience = ConfigurationManager.AppSettings["ida:Audience"],
Tenant = ConfigurationManager.AppSettings["ida:Tenant"],
});
Currently I have the same problem and trying to figure out a solution.
That's what I found out:
After authentication you get back a JSON Web Token (see this page https://msdn.microsoft.com/en-us/library/azure/dn645542.aspx). After decoding this, there are several information available. But I am not sure which of those could possibly make sure to only allow login of the specified Active Directory.
#Aram refers to the values audience (aud) and tenant (tid). Unfortunately audience is always set to the app_id given with the request and tenant is always set to the tenant-id of the Azure tenant, although you are using a live.com account, for example.
Finally, I came up with the idea of checking for the existence of oid (»Object identifier (ID) of the user object in Azure AD.«, https://msdn.microsoft.com/en-us/library/azure/dn645542.aspx). I hope that this one will only be set if the user is part of the Active Directory that is issuing the authorization.
As a result, I set my app up to do the following: If in the decoded version of the id_token of the Access token response there is no oid property set – the login-request will be rejected.
Problem is: I can't confirm that my approach works, because I don't have a second Azure AD and can't check if only live/hotmail/... users will not be given a oid, but also users from different ADs. Maybe #bobbyr you could try that out and report?
Thanks to Thomas Ebert's prompt I've figured out a way to solve my problem. I don't know if it will help anyone else, but...
Basically when my app gets the token from Azure, before passing it on to the client, I can decode the JWT and just look at the email field.
In my case if the email address isn't one that belongs to my domain I can just send a 401 unauthorized back to the client.
It feels weird that Azure doesn't offer some way of doing this via config, maybe it does, but noone has answered this for me, and I've read enough of their docs now to want to pull my own eyes out so I never see the word Azure again...

Twitter API - Reasons for "invalid or expired token"

What are the possible reasons that can cause token to become expired (besides having the user un-authorising the app)?
My problem is that I have an app with several thousands of users, all API communication works perfectly but for some users I am getting the invalid or expired token error, my initial though was that they are users who canceled the authentication to the app but I've contacted some of them and they haven't revoked the access.
Any ideas what other issues can cause that error?
Check the integrity of an access token at any time by calling the GET account/verify_credentials while using that access token.
Its mentioned and by research I came to know that:
Your access token will be invalid if a user explicitly rejects your
application from their settings or if a Twitter admin suspends your
application. If your application is suspended there will be a note on
your application page saying that it has been suspended.
Why is my twitter oauth access token invalid / expired ?
Check this post: invalid / expired access tokens.
There is one post in google groups that says:
You don't get a second chance, and this is by design. OAuth requests
have a unique signature; once a particular request is submitted, it
can't be submitted again.
If they enter the pin correctly, all is well, you get an access token.
If they enter the pin wrong, you get 401 Unauthorized - which is
expected.
But if they then try again to enter the pin, even the correct pin
shows as unauthorized.
Check this link for the above reference.
Some suggestions by twitter employee for the same problem:
I guess there are two things I would suggest at this point: 1.) Go to
your application settings and use the "Reset keys" tab to reset your
consumer key and secret, then update those values in the app and
verify that you still see the same behavior. 2.) Try passing
oauth_callback in your request_token call. Honestly I don't think this
will make a difference, but I want to try and be as rigorous as I can
here.
Also check this discussion saying:
You need to use the oauth_token and oauth_token_secret returned from
the oauth/access_token call instead of the one in your app's settings
in dev.twitter.com
I was getting same error then I changed (access_token) to (access_token_key) and it worked for me.
I hope it will help someone.
In addition to the comments everyone else has made, sometimes the twitter api will return a "invalid token" error when the token isn't the problem. I've noticed it the most when I've built a request string that doesn't parse correctly. For example, once I was getting that error when I was passing in screen_name's that had symbols that weren't URI-encodable. I also have gotten it when I passed in empty values like this (where the cursor is empty):
https://api.twitter.com/1/followers.json?cursor=&screen_name=whatevah
Could you give us the specifics of the calls that are returning this error?
Have you confirmed that the tokens worked at one time? In an OAuth system I worked on, there was an error in how tokens were securely stored and retrieved that caused a small percentage of them to become corrupted. If you can confirm that the tokens worked in the past, that's a good first step.
When you retrieve the tokens from storage, are they unchanged? Is it possible for them to get corrupted with the way you're managing them?
Put some logging in place to keep track of when tokens work and fail. Does a token ever start working again after it has failed once? If you fail to use a token for 30 days, does it expire? With a detailed log, you can start identifying the expired tokens and look for patterns in use to point to what might cause them to expire.
Be sure to explore other possibilities as well. How do users revoke tokens in Twitter? Is it easy to accidentally do that? For users with failed tokens, do they have other authorized apps that have stopped working as well?
First of all nice question Ran.
I want to ask you that have you gone through Twitter developers??
Sometimes it becomes ambiguous that which token to use since Twitter provides two pairs of tokens and the library.One of them is a secret key.
You need to select those token which starts with your Twitter ID followed by a hyphen.
Now your question is this error happens with some of yours users. So here is the answer that an app itself finds ambiguous to choose the token.
Though I might not be completely right, but I recommend you to try this solution at least once.
It might be possible these users have not revoked access. But in my experience an access token can also get expired after the user (in test cases: me) changed his/her password.
When the user does that, you can no longer use the REST API of stream API on that user's scope. Please adapt your application to handle with that situation. Revoke the user's session, so when he comes back to your application, he/she can be redirected to Twitter again to start a new OAuth access token process. Or send him/her an e-mail to kindly ask to reconnect. Vimeo/Windows/... are some of the people handling expired tokens with e-mails.
Have fun!
My God's answer is correct but I will share my answer from another question explaining how it could be your computer's clock:
If your OAuth flow was working one day and failing the next, check your computer's clock. I was running a Vagrant box that somehow had its time set to the day before, which caused the Twitter API to return {"code":89,"message":"Invalid or expired token."}. This may also appear as 401 timestamp out of bounds. You can use this command to update your clock in Ubuntu:
sudo ntpdate time.nist.gov
Alternative method if ntpdate isn't available on your system:
sudo date -s "$(wget -qSO- --max-redirect=0 google.com 2>&1 | grep Date: | cut -d' ' -f5-8)Z"
if your Access Token=738629462149844993-FcWHjfcucCLGEosyGGQ38qI******iC then don't forget to mention hyphen (-) followed by your USERID.
May be this will be helpful for you.I faced the same problem.
Please find the below piece of code snippet
$code = $tmhOAuth->user_request(array(
'method' => 'POST',
'url' => $tmhOAuth->url('oauth/access_token', ''),
'params' => array(
'oauth_verifier' => trim($params['oauth_verifier']),
)
));
if ($code == 200) {
$oauth_creds = $tmhOAuth->extract_params($tmhOAuth->response['response']);
// echo '<pre>';print_r($oauth_creds);exit;
$tmhOAuth->reconfigure(array_merge($tmhOAuth->config, array(
'token' => $oauth_creds['oauth_token'],
'secret' => $oauth_creds['oauth_token_secret'],
)));
$code = $tmhOAuth->user_request(array(
'url' => $tmhOAuth->url('1.1/account/verify_credentials')
));
}
The error invalid or expired token can be linked with the fact that one is not paying.
Without paying one will only be able to create the dev environment (sandbox).
As I have answered here:
Counts is only available to paid premium accounts, and one needs to pay for premium access.
Use this link to Apply for access.
Try to regenerate the keys again and save them properly.
For me, it happened because after regenerating one of the keys I did not update other keys. Therefore removed and regenerated all 4 keys again (CONSUMER_KEY, CONSUMER_SECRET, ACCESS_KEY, ACCESS_SECRET). And tried to execute it again and it worked this time.

How can I use Google's OpenID and/or OAuth services to login and allow access to APIs with only ever one prompt to the user?

I am attempting to create a login system for my website that permits both authentication via Google's API and access to any of the OAuth-supported Google Data APIs while ideally only showing the user one prompt ever, no matter if he's creating an account or logging into his existing one. I want to minimize the number of times he's asked for approval.
I am aware that Google provides Hybrid OpenID/OAuth for this purpose, but the issue is that every time I add OAuth extensions to my OpenID request, it never remembers the user's approval for that request. Is there any way for the approval to be remembered when I am doing Hybrid OpenID/OAuth? If I just do OpenID without OAuth extensions, everything is remembered just fine and it doesn't keep bugging the user with the prompt.
Here are the pertinent extensions I'm sending in addition to my OpenID request, which result in me getting an OAuth request token (good) but cause the approval to never get remembered (bad).
PHP syntax:
$args["openid.ns.ext2"] = 'http://specs.openid.net/extensions/oauth/1.0';
$args["openid.ext2.consumer"] = 'www.MYSITE.com';
$args["openid.ext2.scope"] = 'http://www-opensocial.googleusercontent.com/api/people/';
$args["openid.mode"] = 'checkid_setup';
$args["openid.realm"] = 'http://www.MYSITE.com/';
Is it normal for Hybrid OpenID/OAuth to act this way (not remembering the last OAuth authorization)? What is the best way to get around this? I have thought of storing cookies on the user's computer to link to somewhere in my database so I could use the last access token again, etc... (the issue here being I don't know whose token to look up unless I know who the user is...a circular problem). And doing an OpenID-only request to get his user ID to see if he has an account in order to look up his access token, followed by an OpenID+OAuth request (if an access token for him isn't stored) would result in two prompts, which really wouldn't help.
It also seems like Hybrid only supports OAuth 1.0, which I think is fine until 2015, so it's not an issue right now for me. I am assuming they will support OAuth 2.0 in the future.
Is checkid_immediate relevant to this in any way? I'm just not sure how to use this to accomplish what I want.
I would suggest using OAuth 2.0. This supports getting both identity and access to APIs -- so accomplishes the same end goal, but is much easier than OAuth 1 Hybrid.
Take a look here:
https://developers.google.com/accounts/docs/OAuth2Login
The scopes you're trying to access are included in the URL (see "Forming the URL"). The referenced doc lists the scopes required for getting identity/profile information. You can simply add additional scopes to the string, comma-delimited in order to request access to other APIs. The resulting access token will access both the APIs and identity information (via the UserInfo API endpoint mentioned).
That said, what you're trying to do with OpenID 2.0/OAuth 1 hybrid should work-- and the user should see a checkbox for "remembering" the authorization. If you really want to debug this further, it'd be helpful to have a webpage you can point to which kicks off this authentication+authorization flow so we can see what's happening.
I figured out that checkid_immediate (and x-has-session, not sure if that's needed or even working) is allowing me to determine whether or not a user is logged in without prompting him, and if he is, it is giving me a claimed_id by which I can identify the user. That's exactly what I needed. The original question is solved, but I do want to figure out how to use identify with OAuth 2.0 because I have already implemented that.
Furthermore, I've noticed that when using OpenID/OAuth that the user still gets asked to authorize OAuth even after he's authorized OpenID. I can't see the advantage to the hybrid approach from the user's perspective.
If the user is logged out of Google, that's a total of three prompts just to sign up for my website and grab his name and profile image.
If anyone wondered, here are the steps necessary to get Hybrid OpenID/OAuth completely working (an overview). I was confused thoroughly throughout this process, so I hope this helps someone.
Do normal OpenID handshake and add on AX extensions for OAuth 1.0.
Use 'checkid_immediate' to permit probing for an active Google session without prompting the user. Use *claimed_id* as a unique identifier to link the user to your database.
If 'setup_needed' is returned, use 'checkid_setup' so the user is prompted and verified before continuing.
This leaves you with two possibilities. *checkid_immediate* returning immediately giving you a claimed_id, or a claimed_id coming through after *checkid_setup* (basically sign-up) succeeds.
Hybrid OpenID/OAuth 1.0 will give you an authorized request token.
Use the authorized request token to get an access token (you only need to call OAuthGetAccessToken)
Use that OAuth 1.0 access token to do whatever you want.
I was successful in using OAuthGetAccessToken to get an access token from the authorized request token my Hybrid OAuth dance, omitting the 'oauth_verifier' parameter (irrelevant to Hybrid).
I was successful in using OAuthGetAccessToken to get an access token after my Hybrid OAuth dance, omitting the 'oauth_verifier' parameter (irrelevant to Hybrid).
In a PHP/Zend environment:
$config = array(
'accessTokenUrl' => 'https://www.google.com/accounts/OAuthGetAccessToken',
'consumerKey' => $consumer_key,
'consumerSecret' => $consumer_secret
);
$consumer = new Zend_Oauth_Consumer($config);
$zendRToken = new Zend_Oauth_Token_Request(); // create class from request token we already have
$zendRToken->setToken($requestToken);
try{
$accessToken = $consumer->getAccessToken(array(
'oauth_token' => $requestToken,
// 'oauth_verifier' => '', // unneeded for Hybrid
'oauth_timestamp' => time(),
'oauth_nonce' => md5(microtime() . mt_rand()),
'oauth_version' => '1.0'
), $zendRToken);
} catch (Zend_Oauth_Exception $e){
echo $e->getMessage() . PHP_EOL;
exit;
}
echo "OAuth Token: {$accessToken->getToken()}" . PHP_EOL;
echo "OAuth Secret: {$accessToken->getTokenSecret()}" . PHP_EOL;