How to get refresh token using access token in scribe - oauth

i have got access token now i want to have refresh token so that i can refresh my access token whenever needed.
i used fallowing code but it returned error response
**OAuthRequest request = new OAuthRequest(Verb.POST, "https://accounts.google.com/o/oauth2/token");
request.addBodyParameter("grant_type", "refresh_token");
request.addBodyParameter("refresh_token", "accesstoken string");
request.send();**
any ideas how to get refresh token??????

You can do that using the following code
OAuthRequest request = new OAuthRequest(Verb.POST, "https://accounts.google.com/o/oauth2/token");
request.addBodyParameter("grant_type", "refresh_token");
request.addBodyParameter("refresh_token", accessToken.getToken()); // were accessToken is the Token object you want to refresh.
request.addBodyParameter("client_id", your clientID);
request.addBodyParameter("client_secret", your clientSecret);
Response response = request.send();

A refresh token is obtained in offline scenarios as mentioned in https://developers.google.com/accounts/docs/OAuth2WebServer#offline
Make sure access_type is 'offline'

Actually Scribe doesn't let you to get a refresh token. I had to customize it to make it posible, I did it because i didn't have choice, even the owner(Jerome Leleu) of that library doesn't give maintenance, he is working in a new version called Pac4j.

Related

(iOS) Firestore document snapshotListener stops working 1 hour after signing in

I implemented firebase/auth and use that to sign into firebase using a custom token that I get from our API.
Auth.auth().signIn(withCustomToken: result.data.token) { (authResult, error) in
completion(authResult != nil && error == nil)
}
Then I subscribe to my document using a snapshotListener.
guard let user = Auth.auth().currentUser else {
return
}
listListener = firestoreDB.collection(shoppingListCollectionName).document(user.uid).addSnapshotListener { (documentSnapshot, _) in ....
The listener works for roughly 1 hour and then it stops working. In the logs I get:
Stream error: 'Unauthenticated: Missing or invalid authentication.'
And then I get spammed with:
Stream error: 'Unknown: An internal error has occurred, print and inspect the error details for more information.'
I don't know much the about custom token as you are using custom token to authenticate. But if we are coming to the firebase authentication, the id token issued by firebase has a lifespan of a maximum of one hour. After that the firebase will issue a new id token using the refresh token. I think your id token is getting expired and it is not getting issued again.
The Firebase ID tokens last for only one hour. As you are using a custom token, if you want stay authenticated beyond one hour you will need to use the Firebase Auth REST API. So you will have to make an HTTP request to get an ID token and a refresh token from your custom token (check the Exchange custom token for an ID and refresh token section). Then, you will just have to refresh the ID token every time it expires (check the Exchange a refresh token for an ID token section).

New "OAuth2 Authorization code was already redeemed" error when getting an access code for an Office 365 resource

We have the following steps to authenticate with Office 365 and get the access tokens required to request calendar events...
Send the user to https://login.microsoftonline.com/common/oauth2/authorize?response_type=code , passing the client id and a redirect URL
The user logs in and is redirected back to the redirect URL with a ?code= query string value
Make an API request to https://login.microsoftonline.com/common/oauth2/token to get a token for the https://api.office.com/discovery/ resource, passing the code that we got in step 2
Store the access token and refresh token which is returned
Make an API request to https://api.office.com/discovery/v2.0/me/services to get a list of end points that we have access to
For the end point that I want to work with (Office 365 Exchange) , make an API request to https://login.microsoftonline.com/common/oauth2/token to get a token for the https://outlook.office365.com/ resource, passing the code that we got in step 2
Store the access token and refresh token which is returned
Use the access token from step 7 to fetch calendar events
This used to work fine, but today I'm getting a different result from the API call on step 6
I used to get an access token and refresh token which I could use for the outlook.office365.com resource, but now I'm getting an error message like the following...
{
"error":"invalid_grant",
"error_description":"AADSTS70002: Error validating credentials. AADSTS54005: OAuth2 Authorization code was already redeemed, please retry with a new valid code or use an existing refresh token.
Trace ID: 37f11c2c-6450-4040-b297-48268c6d4b00
Correlation ID: afdeb0cb-c14a-4267-9a5d-2422a1f84d62
Timestamp: 2019-01-29 22:26:24Z",
"error_codes":[70002,54005],
"timestamp":"2019-01-29 22:26:24Z",
"trace_id":"37f11c2c-6450-4040-b297-48268c6d4b00",
"correlation_id":"afdeb0cb-c14a-4267-9a5d-2422a1f84d62"
}
So it looks like I need to pass a different code the second time I make a request to get access tokens, but where do I get this different code from?

Unauthenticated user to authenticated user on AWS Cognito

My code is here: code
Reposted because I wanted to ask a more direct question. How do I switch between unauthenticated user and authenticated? My unauthenticated seems cached and I've used these methods:
[credentialsProvider clearCredentials];
[credentialsProvider clearKeychain];
before the rest of my api code and it still doesn't work. Any help is appreciated
Note: I know it's not working because I make a call using lambda right after I switch up my configuration/credentials provider and only authorized users should be able to call this method.
EDIT #behrooziAWS answer:
API CODE:
id<AWSCognitoIdentityProvider> identityProvider = [[DeveloperIdentityProviderClass alloc] initWithRegionType:AWSRegionUSEast1
identityId:nil
identityPoolId:#"SOMEIDENTITYPOOLID"
logins:#{#"MYIDENTITYPROVIDERNAME": #"MYUSERNAME"}
providerName:#"MYIDENTITYPROVIDERNAME"
];
[credentialsProvider setIdentityProvider:identityProvider];
[credentialsProvider setLogins:#{#"MYIDENTITYPROVIDERNAME": #"MYUSERNAME"}];
[[credentialsProvider refresh] continueWithBlock:^id(BFTask *task){
[self testAuth];
return [BFTask taskWithResult:nil];
}];
Full Error:
BusyTime[27043:7097936] AWSiOSSDKv2 [Verbose] AWSURLResponseSerialization.m line:87 | -[AWSJSONResponseSerializer responseObjectForResponse:originalRequest:currentRequest:data:error:] | Response body: [{"message":"The security token included in the request is invalid."}]
2015-10-20 08:51:17.280 BusyTime[27043:7097936] Error: Error Domain=com.amazonaws.AWSLambdaErrorDomain Code=0 "The operation couldn’t be completed. UnrecognizedClientException" UserInfo=0x7ff27ab41150 {NSLocalizedFailureReason=UnrecognizedClientException, responseStatusCode=403, message=The security token included in the request is invalid., responseHeaders={type = immutable dict, count = 6,
IMPORTANT EDIT: I've hardcoded my refresh to use a working token and identityId. so:
self.identityId = #"someID";
self.token = #"someToken";
return [super getIdentityId];
and then ALL my code is working. But obviously this isn't sustainable, I need to be able to make a call to aws lambda to refresh my credentials. But when I set my identity provider, and set my login, I think it's changing me to my authenticated version, but I need to be in unauthenticated to call aws lambda. Please refer to my code link above and take a look at my refresh method to understand what I'm poorly trying to describe. Also please let me know if this should go in a new thread as this is a slightly different question. Not so familiar with stackoverflow's policies on questions.
Another error: [{"Message":"User: arn:aws:sts::445291524102:assumed-role/Cognito_BusyTimeAuth_Role/CognitoIdentityCredentials is not authorized to perform: lambda:InvokeFunction on resource: arn:aws:lambda:us-east-1:445291524102:function:login"}], SO now I'm assuming my auth provider for my refresh which is incorrect login flow. I'm thinking that I switch this up so that I login in my API class. When I return my identity ID and token, I save them to keychain. Finally, I use the above API code to switch my logins and in my refresh method, I simply return what I found in my keychain. The only problem is I'm not sure if this flow is correct because it doesnt actually "refresh" as I'm not calling my backend. I was wondering if I could wrap the refresh by changing back and forth from my unauth role to my auth role but this seems messy.
[credentialsProvder clearKeychain] will clear the identityId, credentials and any logins, so clearCredentials is unnecessary: clearKeychain Documentation
Normally you don't want to clear your identity id when you transition to an authenticated user. If you simply add your provider and valid login token to the logins map and call [credentialsProvider refresh], you will become authenticated with the same identity id. From that point forward, you will only be able to access that identity if you provide a valid login token. If you want to switch identities by logging out and then login as a authenticated user, that is when you use clearKeychain.

Google Oauth 2.0 Token Expire Time

To start I am using the Google OAuth 2.0 code from this site https://github.com/google/google-api-php-client
I need to find out where in this oauth directory the token expires and logs you out. I am having issues with the refresh token and usually the token expires in 1 hour and throws me an error, but I cant keep waiting for 1 hour each time I make a change to see if the code works or not. I have changed some time settings in the code to like 10 or 60 seconds but they don't do anything. Please let me know which file and where I can change the time the token expires and logs out the logged in user.
Thanks,
I have added the following code because the problem is in here, something with this get function is not renewing/using the refresh token. How can I write this code better.
$service = new Google_Service_Oauth2 ($client);
if ($client->getAccessToken()) {
//For logged in user, get details from google using access token
$user = $service->userinfo->get();
$user_id = filter_var($user['id'],FILTER_SANITIZE_SPECIAL_CHARS);
$user_name = filter_var($user['name'], FILTER_SANITIZE_SPECIAL_CHARS);
$first_name = filter_var($user['given_name'], FILTER_SANITIZE_SPECIAL_CHARS);
$last_name = filter_var($user['family_name'], FILTER_SANITIZE_SPECIAL_CHARS);
$email = filter_var($user['email'], FILTER_SANITIZE_EMAIL);
// $profile_url = filter_var($user['link'], FILTER_VALIDATE_URL);
$profile_image_url = filter_var($user['picture'], FILTER_VALIDATE_URL);
$gender = filter_var($user['gender'], FILTER_SANITIZE_SPECIAL_CHARS);
// $personMarkup = "$email<div><img src='$profile_image_url?sz=50'</div>";
$_SESSION['upload_token'] = $client->getAccessToken();
}
There is no way to change Google's access token expiry time. However, the Google_Client::isAccessTokenExpired() method will return true if the token has expired or expires in 30 seconds from now. Your code should not need to deal with renewing a token only after it fails but can check if the access token is expired before it is going to call any method with that particular access token.
There's still an edge case that remains: you can simulate that by manually revoking the access token (out-of-band of your app) using:
curl https://accounts.google.com/o/oauth2/revoke?token=<access_token>
and then run/test your code that still holds on to the now revoked access token. The error code on access is the same for revoked or expired ("invalid_token"), and the handling is the same anyhow.

Token Response Exception after 2-3 min in retriving Google Contacts of user

I am getting Token Response Exception after 1-2 min continuously. After 2-3 min contacts coming and then after 2-3 min again token exception is coming.
Below is the Exception
com.google.api.client.auth.oauth2.TokenResponseException: 403 OK
<p class="large"><b>403.</b>
<ins>That's an error.</ins></p><p class="large">You are not authorised to perform this request. <ins>That's all we know.</ins>
</p>
I am retriving contacts of user , Below is my code,
ContactsService contactService = new ContactsService("appName");
contactService.setOAuth2Credentials(getCredentials());
Below is getCredentials() method.
public GoogleCredential getCredentials() {
GoogleCredential credential = null;
try{
Collection<String> SCOPES = new ArrayList<String>();
SCOPES.add("https://www.googleapis.com/auth/userinfo.profile");
SCOPES.add("https://www.google.com/m8/feeds");
HttpTransport httpTransport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();
credential = new GoogleCredential.Builder().setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(SCOPES)
.setServiceAccountUser(adminEmailAddress)
.setServiceAccountPrivateKeyFromP12File(new java.io.File(SERVICE_ACCOUNT_PKCS12_FILE_PATH))
.build().setExpiresInSeconds(min);
credential.refreshToken();
} catch(Exception e){
e.printStackTrace();
}
return credential;
}
can anyone tell me how to keep token valid for max time or how to deal with above problem.?
You need to understand how Oauth2 works I think you should read
Using OAuth 2.0 to Access Google APIs
Refresh the access token, if necessary.
Access tokens have limited lifetimes. If your application needs access
to a Google API beyond the lifetime of a single access token, it can
obtain a refresh token. A refresh token allows your application to
obtain new access tokens.
Note: Save refresh tokens in secure long-term storage and continue to
use them as long as they remain valid. Limits apply to the number of
refresh tokens that are issued per client-user combination, and per
user across all clients, and these limits are different. If your
application requests enough refresh tokens to go over one of the
limits, older refresh tokens stop working.
As stated in the doucmentation access tokens work for a limited amount of time. That being 1 hour you can't extend that. But you have the refreshToken you need in order to get a new AccessToken. RefreshTokens dont expire unless the user revokes your access. But in your case this wont happen becouse you are using a service account. So you can just rerun your code and get a new AccessToken
You have two options:
Check the time that is returned if your access token is about to expire then rerun the code and get a new one.
Wait until you get the error message then request a new access token.
The first option is best becouse google logs the number of errors you get from the API no reason to run something thats going to error on you. I normally request a new AccessToken 5 minutes before my old one is due to expire.

Resources