I'm writing a Twitter client.
I have the access_token and refresh_token but I don't have the access_token_secret.
{"scope"=>"tweet.read offline.access", "expires_in"=>7200, "token_type"=>"bearer", "access_token"=>"a...E", "refresh_token"=>"NW...E", "raw_attributes"=>{"scope"=>"tweet.read offline.access", "expires_in"=>7200, "token_type"=>"bearer", "access_token"=>"aD...E", "refresh_token"=>"NW...E"}}
I would like to access the user's home timeline, how can I do that?
Here is the code for the client if it's relevant:
#client ||= TwitterOAuth2::Client.new(
identifier: credentials.client_id,
secret: credentials.client_secret,
redirect_uri: redirect_uri
)
uri = client.authorization_uri(scope: scope.split)
update!(extras: {code_verifier: client.code_verifier})
uri
client.authorization_code = code
update!(extras: client.access_token!(extras["code_verifier"]))
Related
My application is using OAuth to access the Youtube Data API. My OAuth callback is written in node and uses the OAuth2Client class from the "googleapis" npm package to exchange the authorization code for the access and refresh tokens.
Everything was working fine up to last week until suddenly I started getting the "invalid_grant" response during the authorization code exchange. I have tried everything to resolve this and am running out of ideas. My callback executes as a cloud function so I don't think that it would be out of sync with NTP.
My OAuth consent screen is in "Testing" mode and my email address is included in the test users. The odd thing is that even though the authorization code exchange fails, my Google account's "Third-party apps with account access" section lists my application as if the handshake succeeded.
Is there a limit to how many refresh tokens can be minted for my application? I am testing my implementation of incremental authorization so I have been going through the OAuth flow often.
Edit
I've included my code for generating the auth URL and exchanging the authorization code below. The invalid_grant occurs during the call to "oauth2.getToken"
async startFlow(scopes: string[], state: string): Promise<AuthFlow> {
const codes = await oauth2.generateCodeVerifierAsync();
const href = oauth2.generateAuthUrl({
scope: scopes,
state,
access_type: 'offline',
include_granted_scopes: true,
prompt: 'consent',
code_challenge_method: CodeChallengeMethod.S256,
code_challenge: codes.codeChallenge
});
return { href, code_verifier: codes.codeVerifier };
}
async finishFlow(code: string, verifier: string): Promise<Tokens> {
const tokens = await oauth2.getToken({ code, codeVerifier: verifier })
return {
refresh_token: tokens.tokens.refresh_token!,
access_token: tokens.tokens.access_token!,
expires_in: tokens.tokens.expiry_date!,
token_type: 'Bearer',
scopes: tokens.tokens.scope!.split(' ')
};
}
"oauth2" is an instance of OAuth2Client from "google-auth-library". I initialize it here:
export const oauth2 = new google.auth.OAuth2({
clientId: YT_CLIENT_ID,
clientSecret: YT_CLIENT_SECRET,
redirectUri: `${APP_URI}/oauth`
});
Looking at the logs, the only out of the ordinary thing I notice is that the application/x-www-form-urlencoded body looks slightly different than the example https://developers.google.com/identity/protocols/oauth2/web-server#exchange-authorization-code
The POST request to "https://oauth2.googleapis.com/token" ends up looking like this:
code=4%2F0AX4XfWiKHVnsavUH7en0TywjPJVRyJ9aGN-JR8CAAcAG7dT-THxyWQNcxd769nzaHLUb8Q&client_id=XXXXXXXXXX-XXXXXXXXXXXXXXX.apps.googleusercontent.com&client_secret=XXXXXX-XXXXXXXXXXXXXXX-XX_XXX&redirect_uri=https%3A%2F%2Fapp.example.com%2Foauth&grant_type=authorization_code&code_verifier=KjOBmr4D9ISLPSE4claEBWr3UN-bKdPHZa8BBcQvcmajfr9RhWrgt7G429PLEpsP7oGzFGnBICu3HgWaHPsLhMkGBuQ2GmHHiB4OpY2F0rJ06wkpCjV2cCTDdpfRY~Ej
Notice that the "/" characters are not percent-encoded in the official example, but they are in my requests. Could this actually be the issue? I don't see how the official google auth library would have an issue this large.
The most common cause for the invalid_grant error is your refresh token expiring.
If you check oauth2#expiration you will see the following
A Google Cloud Platform project with an OAuth consent screen configured for an external user type and a publishing status of "Testing" is issued a refresh token expiring in 7 days.
Once you set your project to production your refresh tokens will stop expiring.
Is there a limit to how many refresh tokens can be minted for my application?
No but you have a limit of 100 test users.
I want to access my todo list using Microsoft graph API and so registered an app and after doing the required steps got the access token, but after trying to get the new access token using the refresh token it returns this message: "error": "unauthorized_client", "error_description": "AADSTS700016: Application with identifier 'id' was not found in the directory 'Microsoft Accounts'. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You may have sent your authentication request to the wrong tenant
class Refresh:
def __init__(self):
self.refresh_token = refresh_token
self.scope = scope
self.client_secret = client_secret
def refresh(self):
query = "https://login.microsoftonline.com/common/oauth2/v2.0/token"
response = requests.post(query,
data={"client_id" : client_id,
"scope": 'Tasks.Read%20Tasks.Read.Shared%20Tasks.ReadWrite%20Tasks.ReadWrite.Shared%20offline_access',
"refresh_token": refresh_token,
"redirect_uri": 'https://github.com/Rohith-JN',
"grant_type": "refresh_token",
"client_secret": client_secret
},
headers={"Content-Type": "application/x-www-form-urlencoded"})
response_json = response.json()
print(response)
print(response_json)
a = Refresh()
a.refresh()
I am also not sure if I am entering the scopes in the right way. Any help would be really appreciated
I finally figured it out by changing the URL that refreshes the token from
https://login.microsoftonline.com/common/oauth2/v2.0/token to this https://login.microsoftonline.com/{tenant_id}/oauth2/token
I am using react-native-app-auth library and passing in grant type: authorization code with PKCE and client credentials
const config = {
issuer: "***",
clientId: "***",
clientSecret: '***',
redirectUrl: '***:/oauthredirect',
additionalParameters: {},
scopes: ['***']
}
const newAuthState = await authorize(config);
Able to enter credentials and redirect to react native app but getting error of client_id and client_secret is missing or has an incorrect value
client_id, client_secret and scope are correct. And scope, redirectUrl are registered on server.
https://github.com/FormidableLabs/react-native-app-auth
clientAuthMethod - (string) ANDROID Client Authentication Method. Can be either basic (default) for Basic Authentication or post for HTTP POST body Authentication
passing clientAuthMethod as post worked for me.
This code is from the google oauth example.
const config = {
issuer: 'https://accounts.google.com',
clientId: 'GOOGLE_OAUTH_APP_GUID.apps.googleusercontent.com',
redirectUrl: 'com.googleusercontent.apps.GOOGLE_OAUTH_APP_GUID:/oauth2redirect/google',
scopes: ['openid', 'profile']
};
// Log in to get an authentication token
const authState = await authorize(config);
However, after signing in and being redirected to the app, I get an error:
client_secret is missing
Adding clientSecret to the config fixes the problem on iOS. However, on android, adding clientSecret does not allow me to log in with google and instead loads this error page saying that client_secret is not allowed.
So it's a little bit of a catch-22. If I provide the clientSecret, I get an invalid request error from google and can't authenticate. If I don't provide it, I get "client_secret is missing" error after authenticating.
Add the SHA1 key in the firebase and make sure there is support email present.
Put the following in the config:
clientSecret: 'YOUR_SECRET_KEY',
I'm new to office 365 and having problem with accessing rest api.
I'm trying to test the rest api of Calendar and Mail API, so I decided to use Postman. However, to test those APIs, I need an access token in Authorization header. To figure out how to get a token, I decided to get the sample project here , configure, run and sign in on this local site to get the token cached in local storage and use that token for further requests in Postman. However, all requests I tested returned '401 unauthorized request'.
What I did:
Register a new app on Azure ADD associated with O365 account
Add full app permissions and delegated permissions.
Update 'oauth2AllowImplicitFlow' to true in manifest file.
Clone sample project
In app.js, I change the alter the content of config function as following
function config($routeProvider, $httpProvider, adalAuthenticationServiceProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/home.html',
controller: 'HomeController',
controllerAs: 'home',
requireADLogin: true
})
.otherwise({
redirectTo: '/'
});
// The endpoints here are resources for ADAL to get tokens for.
var endpoints = {
'https://outlook.office365.com': 'https://outlook.office365.com'
};
// Initialize the ADAL provider with your tenant name and clientID (found in the Azure Management Portal).
adalAuthenticationServiceProvider.init(
{
tenant: 'mytenantname.onmicrosoft.com',
clientId: '<my cliend Id>',
endpoints: endpoints,
cacheLocation: 'localStorage'
},
$httpProvider
);
};
Then I ran the app, it sign me in just fine and I can also get the token, but that token is also unauthorized to request.
I decoded the token and saw the value of 'aud', it didn't return "https://outlook.office365.com/". In this url, the author said that "This should be "https://outlook.office365.com/" for the Mail, Calendar, or Contacts APIs"
So what did I miss ?
How you call the Office 365 API in AngularJS?
When signing the user in, you will only get the id_token to authenticate the user.
The aud of id_token is the tenant id (GUID).
To call the Office 365 API, you need to use AugularJS http request.
Here is a sample of sending email using Microsoft Graph API in AngularJS:
// Build the HTTP request to send an email.
var request = {
method: 'POST',
url: 'https://graph.microsoft.com/v1.0/me/microsoft.graph.sendmail',
data: email
};
// Execute the HTTP request.
$http(request)
.then(function (response) {
$log.debug('HTTP request to Microsoft Graph API returned successfully.', response);
response.status === 202 ? vm.requestSuccess = true : vm.requestSuccess = false;
vm.requestFinished = true;
}, function (error) {
$log.error('HTTP request to Microsoft Graph API failed.');
vm.requestSuccess= false;
vm.requestFinished = true;
});
Before calling the API, ADAL.js will acquire another token - access token which you can used to send the email.
UPDATE#1
I also downloaded the sample you mentioned. To run this sample, please ensure you have the Exchange Online > Read and writer user mail Permission assigned in your application.