How can i get a Refresh token using the Salesforce OAuth? - oauth

When i first authenticate with OAuth to Salesforce i dont get back a refresh token , i just get back an access token. So if the token needs to be refreshed by using the following:
var client = new RestClient("https://myOrg.salesforce.com/services/oauth2/token");
var request = new RestRequest("", Method.POST);
request.AddParameter("refresh_token", {currentRefreshToken}, ParameterType.GetOrPost);
request.AddParameter("grant_type", "refresh_token", ParameterType.GetOrPost);
request.AddParameter("client_id", {clientId}, ParameterType.GetOrPost);
request.AddParameter("client_secret", {clientsecret}, ParameterType.GetOrPost);
var response = client.Execute(request);
The currentRefreshToken is NULL because i didnt receive any refresh token on the initial authentication response.
The initial call to authenticate is
https://login.salesforce.com/services/oauth2/authorize? client_id={consumer_key}&
redirect_uri={callback_url}& response_type=code
and this doesnt give back a refreshtoken. How can i get an initial refresh token ?

The connected app has to allow issuing refresh tokens (check if "scopes" contains refresh and if there isn't something like "immediately expire refresh tokens" set).
And then you need to ask for it, add optional scope=refresh_token parameter to your request.
https://help.salesforce.com/s/articleView?id=sf.remoteaccess_oauth_user_agent_flow.htm&type=5

Related

Understanding Google OAuth2 Refresh tokens

I previously worked on an OAuth2 application where the logic was to generate a new access token via refresh token once the old one expired.
Now working with Google APIs, I'm not experiencing the same thing. I have received both an access token and refresh token, and after allowing the access token to expire, I attempt to use the refresh token
var myToken = new TokenResponse
{
RefreshToken = sRefreshToken
};
var credentials = new UserCredential(new GoogleAuthorizationCodeFlow(
new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = new ClientSecrets
{
ClientId = clientId,
ClientSecret = clientSecret
}
}), "user", myToken);
service = new CalendarService(new BaseClientService.Initializer()
{
HttpClientInitializer = credentials,
ApplicationName = "XYZ",
});
It seems after doing so I can make API calls. But I have tried to retrieve the access/refresh tokens after doing this with:
ACCESS_TOKEN = credentials.Token.AccessToken;
REFRESH_TOKEN = credentials.Token.RefreshToken;
And both the access and refresh tokens are the same as the old ones. I had thought refreshing would generate a new token altogether? Is this not the case?
If the access token expires after 30 minutes and you then just need to pass in the refresh token (but nothing re-generates), what is the point of the refresh token?
I previously worked on an OAuth2 application where the logic was to generate a new access token via refresh token once the old one expired.
This idea also applies to Google access/refresh tokens. But if you're using the .NET client library (as your code snippet suggests), you don't have to perform the refreshes yourself. You can just continue using the UserCredential object and it'll automatically fetch a new access token every ~1h.

Youtube oAuth promts authorization window every time I make request

Here is my work flow for getting access token and refresh token for youtube api. Im generating authorization url with parameters
access_type=offline, response_type=code, redirect_uri=uri, scope=scopes, state=state, client_id=id
from authorization url I´m receiving authentication code, then I´m generating another url to get access_token and refresh_token using code from authorization url with these parameters
code: code, client_id: CLIENT_ID, client_secret: CLIENT_SECRET, redirect_uri: serviceCallback, state: state.callback, grant_type: "authorization_code"
As far as I know user should complete this process only once and then it should be automatic. My problem is that I´m always have to complete authorization and I´m getting always new access_token and refresh_token without forcing it on request.
here is code part where I´m getting authentication url
getAuthUrl: function(scopes, applicationCallback, serviceCallback, siteId,
selectChannel, websiteUrl) {
var requestedClientId = CLIENT_ID;
var scopess =
"https://www.googleapis.com/auth/yt-analytics.readonly https://www.googleapis.com/auth/youtube.readonly https://www.googleapis.com/auth/userinfo.email " +
scopes.replace(",", " ");
return "https://accounts.google.com/o/oauth2/auth?" +
"access_type=offline" +
"&response_type=code" +
/*"&approval_prompt=auto" +*/
"&redirect_uri=" + serviceCallback +
"&scope=" + scopes +
"&state=" + JSON.stringify({
service: NAME,
callback: applicationCallback,
scopes: scopes,
siteId: siteId,
selectChannel: selectChannel,
websiteUrl: websiteUrl
}) +
"&client_id=" + requestedClientId;
},
From there Im getting back code and using that code, clientID and clientSecret to get access token and refresh token
getAuthTokens: function(code, state, res, serviceCallback) {
// Google oAuth endpoint
var endpoint = "https://www.googleapis.com/oauth2/v4/token";
const scopes = state.scopes.split(" ");
// Setup request data
var data = {
code: code,
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
redirect_uri: serviceCallback,
state: state.callback,
grant_type: "authorization_code"
};
request.post(endpoint).send(data).type('form').set('Accept',
'application/json').end(function(err, oAuthResponse) {});
},
I was using wrong endpoint url I changed it to different one to one provided by youtube api documentation and removed state parameter from data variable but still doesnt fix the problem
new endpoint url
var endpoint = "https://accounts.google.com/o/oauth2/token";
I´m really confused right now because I´m not forcing authorization and on google apps section there is my app already authorized and it does not update authorization that means it gives permission only first time and after that when I´m pressing allow it doesn´t do anything. OAuth should check if I have refresh token or not, so my conclusion is that I don´t fully understand how it should work or I´m somehow testing everything on debug or test mode where authorization prompt is automatically forced.
I would be really thankful for any kind of help because I feel like I tried everything.
The issue is that the access token that you are using has expired before the next time you use as you have not updated the access token manually using the refresh token.
You need to use the refresh token to update the access token if [ (time you last updated the access token) + (the expiry time) ] has already surpassed.
The concept of refresh tokens is that if an access token is compromised, as it is short-lived, the attacker has a limited time period in which it can be used. Refresh tokens, if compromised, are useless because the attacker requires the client id and client secret in addition to the refresh token in order to gain an access token.
The YouTube API documentation demonstrates the procedure here
By default, the expiry time is around 3 seconds.
This will surely, work in your case.
Adding the following parameter to your authentication object may help...depending on your requirements:
prompt: 'none'
This would mean no consent is gained or needed, after an initial authorization to use the app.
Go to the my accounts settings of google for this account---> go to connected apps and sites ----> manage apps:
Over there can you see the permissions for youtube like this:

google authentication expired token

I need to recover user info after javascript google login.
Authentication work fine and i send googleUser.Ka object to my php where there's this code
$api = new Google_Client();
$api->setApplicationName($this->_configCustomer['google']['api']['application_name']);
$api->setClientId($this->_configCustomer['google']['api']['client_id']); // Set Client ID
$api->setClientSecret($this->_configCustomer['google']['api']['client_secret']); //Set client Secret
$api->setAccessType('online'); // Access method
$api->setScopes(array('https://www.googleapis.com/auth/plus.login', 'https://www.googleapis.com/auth/plus.me', 'https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/userinfo.profile'));
//$api->setRedirectUri('http://www.infotuts.com/demo/googlelogin/login.php');
$service = new Google_Service_Plus($api);
$oauth2 = new \Google_Service_Oauth2($api);
$api->setAccessToken(json_encode($_POST));
//ADDED AFTER ERROR
if($api->isAccessTokenExpired()) {
$api->authenticate();
$NewAccessToken = json_decode($api->getAccessToken());
$api->refreshToken($NewAccessToken->refresh_token);
}
//END ADDED AFTER FIRST ERROR
//$api->authenticate($_POST['access_token']);
if ($api->getAccessToken()) {
$data = $service->people->get('me');
$user_data = $oauth2->userinfo->get();
var_dump($user_data);
die();
}
this code generate the error:
The OAuth 2.0 access token has expired, and a refresh token is not available. Refresh tokens are not returned for responses that were auto-approved.
i added code indicate from comment follow this link
OAuth 2.0 access token has expired, and a refresh token is not available
but in the last version of php authenticate method require $code parameter. What is it?
Thanks
i solved in this way
$api = new Google_Client();
$api->setApplicationName($this->_configCustomer['google']['api']['application_name']);
$api->setClientId($this->_configCustomer['google']['api']['client_id']); // Set Client ID
$api->setClientSecret($this->_configCustomer['google']['api']['client_secret']); //Set client Secret
$api->setAccessType('online'); // Access method
$api->setScopes(array('https://www.googleapis.com/auth/plus.login', 'https://www.googleapis.com/auth/plus.me', 'https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/userinfo.profile'));
$api->setRedirectUri('postmessage');
$result = $api->verifyIdToken($_POST['id_token']);
i send id_token, obtained from the ajax login, and recovery user info using verifyIdToken method of client library

Issue exchanging LInkedIn javascript token to rest oauth token

I am using the article located at https://developer-programs.linkedin.com/documents/exchange-jsapi-tokens-rest-api-oauth-tokens to exchange my Javascript access token to a REST OAuth token.
After following the directions here, no matter what I seem to do, I only get a 400 Bad Request response back.
The flow I use for Facebook and want to recreate with LinkedIn is; front end authenticates to LinkedIn and passes an access token to my API, the API then gets all necessary user information and passes my own bearer token back to the client, et voila.
Unfortunately LinkedIn doesn't play so nicely with this, and I need to convert my token to an OAuth token from its Javascript token.
I pass the cookie LinkedIn gives me to my API, it looks something like the below (where OAuthBase is http://oauth.googlecode.com/svn/code/csharp/OAuthBase.cs)
access_token: "oxmKI9aU4RCfksdegZ3obZGHK-vo6Q4-4FSQk"
member_id: "AmjWCF7ExN"
signature: "t8KEbLjJ+r6uM42tUwfJm5yWp70="
signature_method: "HMAC-SHA1"
signature_order: ["access_token","member_id"]
signature_version: "1"
I then am attempting to make a call to https://api.linkedin.com/uas/oauth/accessToken to do the actual exchange. My code for this is:
public async Task<IHttpActionResult> ConvertLinkedInToken(LinkedInCovertTokenObject val)
{
string normalizeduri;
string normalizedparams;
OAuthBase o = new OAuthBase();
string signature = o.GenerateSignature(new Uri("https://api.linkedin.com/uas/oauth/accessToken"), Startup.linkedInAuthOptions.ClientId, Startup.linkedInAuthOptions.ClientSecret, val.access_token, null, "POST", o.GenerateTimeStamp(), o.GenerateNonce(), out normalizeduri, out normalizedparams);
var client = new HttpClient();
var uri = new Uri("https://api.linkedin.com/uas/oauth/accessToken?" +
"oauth_consumer_key=" + Startup.linkedInAuthOptions.ClientId +
"&xoauth_oauth2_access_token=" + val.access_token +
"&signature_method=HMAC-SHA1" +
"&signature=" + signature
);
var response = await client.GetAsync(uri);
return Ok();
}
No matter how I play around all I get back from LinkedIn is a 400 Bad Request without any other useful information.
1) How can I convert LinkedIn JS token to Rest OAuth token in my c# api
This is how I achieved that:
On the frontend:
IN.User.authorize(function(){
// here you can find oauth token
var oauth_token = IN.ENV.auth.oauth_token;
// send this token to your API endpoint
});
On your API (curl example), of course replace OAUTH_TOKEN with token received on the frontend.
curl -X GET \
'https://api.linkedin.com/v1/people/~:
(id,firstName,lastName,siteStandardProfileRequest,picture-url,email-
address)?format=json' \
-H 'oauth_token: OAUTH_TOKEN'
You are looking at old documentation from LinkedIn. Starting from 12th May, LinkedIn has started rolling out new changes in their API which includes authentication. In my knowledge, LinkedIn is not using OAuth anymore, and you need OAuth2.0 henceforth for authentication. You should check this link for more information:
https://developer.linkedin.com/docs/signin-with-linkedin

OAuts with Signpost - how to sign POST to get Access token

I'm working with client who provided me with somewhat vague
instructions. Here's what I'm doing (using CommonsHttpOAuthConsumer as
consumer and DefaultOAuthProvider as provider)
I'm able to get response token from doing this:
String requestToken = provider.retrieveRequestToken
(OAuth.OUT_OF_BAND);
this is in form of URL with params so I'm parsing the actual token
out for example:
https://foobar.com/oauth/login_authorize?oauth_token=XRFCGPbES3M2bYZy...
Now - the instructions that I get say:
Given the request token obtained in step 1, login with the user’s
credentials (name and password) as POST parameters and sign the
request with the request token/secret
POST https://foobar.com/oauth/login_authorize
That's where I'm having difficulties. Obviously I have to input that
requestToken somewhere so I do this (post is HttpPost that contains user credentials):
consumer.setTokenWithSecret(requestToken, SECRET);
consumer.sign(post);
It doesn't work. It actually generates 200 status but what I get is a
generic error message.
retrieveRequestToken does not return a request token, it returns an authenticationUrl that you need to send your users to so they can sign in. Request token is saved in provider object.
String authenticationUrl = provider.retrieveRequestToken( call_back_url )
Note: According to the oauth standard the users sign in on the providers site with their credentials. After they have done that you (as a consumer) can get the Access Token and after that you can access their data on the providers site.
// After user has signed in
provider.retrieveAccessToken(null)
// access token is saved in provider and provider knows which consumer uses it
// so now you can sign with your consumer and connect with the request
URL url = new URL( protected_resources_url )
HttpURLConnection request = (HttpURLConnection) url.openConnection();
consumer.sign(request)
request.connect()
If you have the user credentials you can do the authorization in your script
// Using grails and functional-tests
get(authenticationUrl)
// Image the site shows a simple form with username/password and a login button
setRedirectEnabled false
form {
username = "mario"
password = "peach"
click "login"
}
And then do retrieveRequestToken and the code mentioned above
Hope this helps you
// Jonas

Resources