I have implemented Spring security with oAuth2. I want to refresh our access token before it expire. Please help me how to made request for refresh my access token.
You can make a POST request to oauth/token, see the following AngularJS snippet:
function ajaxRefreshToken(refresh_token) {
return $injector.get('$http')
.post(
'oauth/token',
'grant_type=refresh_token&refresh_token=' + refresh_token,
{
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/json',
'Authorization': 'Basic ' + Base64.encode('***' + ':' + '***')
}
});
}
or, with cURL:
curl -s -u $CLIENT_ID:$SECRET \
'http://$HOST/oauth/token' \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data 'grant_type=refresh_token&refresh_token='$REFRESH_TOKEN
oauth/token?grant_type=refresh_token&client_id=[id]&client_secret=[secret]&refresh_token=[your refresh token]
Send request like above.You should add client details with the request.
Related
Per Account deletion requirement iOS
If your app offers Sign in with Apple, you’ll need to use the Sign in with Apple REST API to revoke user tokens when deleting an account.
Referring to this answer, we are trying to send this revoke token API on our server-side. Here are some snippet
privateKey = fs.readFileSync("xxxxxxxx.p8")
client_secret = jwt.sign({
iss: 'xxxx-xxx-xx-xxxx-xxxxxxxx',
iat: Math.floor(Date.now() / 1000),
exp: Math.floor(Date.now() / 1000) + 1200,
aud: 'https://appleid.apple.com',
sub: "sample.com"
},
privateKey,
{
algorithm: 'ES256',
header: {
alg: 'ES256',
kid: 'xxxxxxxxxxx'
}
});
data = {
'token': token,
'client_id': "sample.com",
'client_secret': client_secret
};
body = qs.stringify(data)
opts =
protocol: 'https:'
host: 'appleid.apple.com'
path: '/auth/revoke'
method: 'POST'
timeout: 6000
headers:
'Content-Type': 'application/x-www-form-urlencoded'
'Content-Length': Buffer.byteLength(body)
// call https to send this opts message
And the status code of the above codes could be 200 and the response body is empty.
However, the response code 200 of revoke token api
The request was successful; the provided token has been revoked successfully or was previously invalid.
It seems the status code 200 includes the provided token was previously invalid. How could we distinguish whether the revoke token API was returned by the invalid token or revoked successfully?
We also try to test this revoke token API through curl with invalid client_secret and token, the status code 200 could be returned either and the response body is empty. It is so weird.
curl -v POST "https://appleid.apple.com/auth/revoke" \
-H 'content-type: application/x-www-form-urlencoded' \
-d 'client_id=xxx.xxxx.yyyy' \
-d 'client_secret=ddddddeyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IlBGUVRYTTVWUlcifQ.dddd.DmMifw6qWHMqKgDIbO8KrIzDvbF7T4WxxEo9TmtN0kmTISsi8D8FG52k_LPGkbNEnS_-w_SRimEKIH1rsuawFA' \
-d 'token=dddddd' \
-d 'token_type_hint=access_token'
> POST /auth/revoke HTTP/1.1
> Host: appleid.apple.com
> User-Agent: curl/7.77.0
> Accept: */*
> content-type: application/x-www-form-urlencoded
> Content-Length: 240
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200
< Server: Apple
< Date: Thu, 09 Jun 2022 07:36:31 GMT
< Content-Length: 0
< Connection: keep-alive
< Host: appleid.apple.com
Finally, we could call revoke token api (appleid.apple.com/auth/revoke) successfully, and the apple id binding information is deleted under Apps Using Apple ID of Settings
The root cause is that an invalid token has been used before. We try the identity token of the apple signing result, it is not the correct token.
The correct token is access_token or refresh_token returned from auth/token.
code - The authorization code received in an authorization response sent to your app. The code is single-use only and valid for five minutes. Authorization code validation requests require this parameter.
In order to get access_token or refresh_token through auth/token, the code parameter of auth/token request should be paid attention. The code authorization response of apple signing, and its type is base64. It should be decoded to utf-8 before assigning to auth/token API.
Summary the whole process as below.
Get authorizationCode from Apple login.
Get a refresh token \ access token with no expiry time using authorizationCode through auth\token
Revoke the refresh token or access token through token\revoke
Hope the above could help someone who meet the same issue. Here are node.js code snippets.
getClientSecret: () ->
client_secret = jwt.sign({
iss: 'xxxxxxxxx',
iat: Math.floor(Date.now() / 1000),
exp: Math.floor(Date.now() / 1000) + 360000,
aud: 'https://appleid.apple.com',
sub: bundleID
},
#privateKey,
{
algorithm: 'ES256',
header: {
alg: 'ES256',
kid: 'xxxxxxxxxx'
}
});
client_secret
decodeBase64: (base64Data) ->
buff = Buffer.from(base64Data, 'base64')
return buff.toString('utf-8')
revokeToken: (token) ->
client_secret = #getClientSecret()
data = {
'token': token,
'client_id': bundleID,
'client_secret': client_secret,
'token_type_hint': 'access_token'
};
body = qs.stringify(data)
opts =
protocol: 'https:'
host: 'appleid.apple.com'
path: '/auth/revoke'
method: 'POST'
timeout: 6000
headers:
'Content-Type': 'application/x-www-form-urlencoded'
'Content-Length': Buffer.byteLength(body)
http.post(body, opts)
authToken: (authCode) ->
client_secret = #getClientSecret()
code = #decodeBase64(authCode)
data = {
'code': code,
'client_id': bundleID,
'client_secret': client_secret,
'grant_type': 'authorization_code'
};
body = qs.stringify(data)
opts =
protocol: 'https:'
host: 'appleid.apple.com'
path: '/auth/token'
method: 'POST'
timeout: 6000
headers:
'Content-Type': 'application/x-www-form-urlencoded'
'Content-Length': Buffer.byteLength(body)
http.post(body, opts)
I am using axios in reactjs which is running on port 3000 & Rails 6 API application is running in 3001.
I hit for /authenticate POST API & checked in the browser network tab for xhr tab where I found status as (cancelled) and no response or error.
On rails log,
Started POST "/api/v1/authenticate" for ::1 at 2020-09-04 09:56:49 +0530
Processing by Api::V1::AuthenticationController#authenticate as HTML
Parameters: {"email"=>"example#mail.com", "password"=>"[FILTERED]", "authentication"=>{"email"=>"example#mail.com", "password"=>"[FILTERED]"}}
Please suggest what I am doing wrong here
My axios call is like below,
const response = await axios({
URL: "http://localhost:3001/api/v1/authenticate",
method: "POST",
data: {"email":"example#mail.com","password":"123123123"},
headers: { 'Content-Type': 'application/json' }
});
I followed reference but did not work
src/setupProxy.js
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function (app) {
app.use(
'/api/v1',
createProxyMiddleware({
target: 'http://localhost:3001/',
changeOrigin: true,
})
);
};
API seems right as following return token in response json data,
curl -H "Content-Type: application/json" -X POST -d '{"email":"example#mail.com","password":"123123123"}' http://localhost:3001/api/v1/authenticate
I'm not sure if you're using Devise or not, but I use Knock for JWT, which has a nasty habit of requiring a data to include auth like this:
const response = await axios({
URL: "http://localhost:3001/api/v1/authenticate",
method: "POST",
data: {"auth": {"email":"example#mail.com","password":"123123123"}},
headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' }
});
while Devise requires additional header Accept: application/json
Refer here -> https://github.com/nsarno/knock#authenticating-from-a-web-or-mobile-application
https://github.com/heartcombo/devise/wiki/API-Mode-Compatibility-Guide
Don't know if this answers your question though.
I'm following this: https://developer.chrome.com/apps/tut_oauth
But it doesn't work. When I invoke Cloud Function, I get 401 error. The Authorization: Bearer "access-token" is added in the request header. Although another question here[1] states that ID_TOKEN should be used. Which I tried via curl but have the same 401 error.
chrome.identity.getAuthToken({interactive: true}, function(token) {
var dat = {
"user_email":email_id,
"user_id":user_id
};
$.ajax({
type: "POST",
data:dat,
dataType: 'json',
url:str,
contentType: "application/json",
error: function (xhr, status, error) {
console.log(xhr)
}, success: function (data, status, xhr) {
console.log('Success!' +data + status);
},
headers:{
'x-goog-project-id': 'xxxxxxxxxxxxx',
'Authorization': 'Bearer ' + token,
'Content-Type':'application/json',
'Accept': 'application/json'
}
});
});
[1] Why doesn't granting 'allAuthenticatedUsers' member the 'Cloud Functions Invoker' role work for google cloud functions?
The tutorial that you mentioned used "access-token" to accesses a user's Google contacts using the Google People API and the Chrome Identity API.
If you want to access a Google Cloud Function which does not Allow unauthenticated invocations you have to use an ID_TOKEN.
For testing you can create a service account with --role="roles/cloudfunctions.invoker", then create a key.json file and export the GOOGLE_APPLICATION_CREDENTIALS env variable link
Finaly you can use:
curl "https://us-central1-your-project.cloudfunctions.net/yourfunction"
# Error 403 (Forbidden)
curl "https://us-central1-your-project.cloudfunctions.net/yourfunction" -H "Authorization: bearer $(gcloud auth print-identity-token)"
#Success
I gave up on this as there is no direct solution to invoke Cloud function using oauth in Chrome Apps. The alternative solution that worked is to authenticate via API key. That is using Cloud Function with Cloud Endpoints.
I followed the logic here: https://medium.com/#akash.mahale/triggering-google-cloud-functions-with-cloud-endpoints-and-api-key-857e94a8a3aa
But just need to take note that rotation of API keys should be done regularly and automatically..
I’m trying to use a cloudflare worker (Pasted below) to send an SMS message via the Twilio API. The CURL request (also pasted below) I’m basing the worker off of works.
Based on the 400 error from the worker the message body isn’t passed in correctly
{"code": 21602, "message": "Message body is required.", "more_info": "https://www.twilio.com/docs/errors/21602", "status": 400}
but the code looks fine to me. We can at least confirm the header is passed correctly because messing with the authorization value changes the error.
I also looked at the example POST request in the template gallery and can’t see a reason for the failure.
https://developers.cloudflare.com/workers/templates/pages/post_json/
What do i need to change in my worker code to make the POST request work?
Note: i recognize i shouldn’t put the Twilio Auth token in the body but I’ll rotate the key later.
async function handleRequest(request) {
const init = {
body: JSON.stringify(body),
method: 'POST',
headers: {
'content-type': 'application/json',
'Authorization': "Basic " + btoa('[account id]:[Authtoken]'),
},
}
return await fetch(url, init)
}
addEventListener('fetch', event => {
return event.respondWith(handleRequest(event.request))
})
const url = 'https://api.twilio.com/2010-04-01/Accounts/[Account id]/Messages.json'
const body = {
Body:"Hello World",
From:"+[some number]",
To:"+[some number]]",
}
curl 'https://api.twilio.com/2010-04-01/Accounts/[Account id]/Messages.json' -X POST \
--data-urlencode 'To=+[some number]' \
--data-urlencode 'From=+[some number]' \
--data-urlencode 'Body=Hello World' \
-u [account id]:[auth token]
because Twilio requires application/x-www-form-urlencoded.
REST API: Your Request
Creating or updating a resource involves performing an HTTP PUT or
HTTP POST to a resource URI. In the PUT or POST, you represent the
properties of the object you wish to update as form urlencoded
key/value pairs. Don't worry, this is already the way browsers encode
POSTs by default. But be sure to set the HTTP Content-Type header to
"application/x-www-form-urlencoded" for your requests if you are
writing your own client.
I'm working with the Harvest API, a pretty standard web service API, and my curl requests are working just fine while my Dart HttpClient requests are not. Here is my curl request (with sensitive information disguised, of course):
curl -H "Content-Type: application/json" \
-H "Accept: application/json" \
-u "address#domain.com:password" \
https://my_domain.harvestapp.com/account/who_am_i
UPDATE --- The following code now works:
HttpClient client = new HttpClient();
client.addCredentials(
Uri.parse('https://my_domain.harvestapp.com/account/who_am_i'),
'realm',
new HttpClientBasicCredentials('address#domain.com', 'password')
);
client.getUrl(Uri.parse('https://my_domain.harvestapp.com/account/who_am_i'))
.then((HttpClientRequest req) {
req.headers
..add(HttpHeaders.ACCEPT, 'application/json')
..add(HttpHeaders.CONTENT_TYPE, 'application/json');
return req.close();
})
.then((HttpClientResponse res) {
print(res);
client.close();
});
}
Obviously I would like to do more than simply print the response, but no matter what, the res object ends up being null, which means that the request is failing in some respect. Does anything seem awry or amiss? I'm at a loss for now.
To summarize the changes from the original code snippet:
Call HttpClient.addCredentials before calling HttpClient.getUrl
In the .then((HttpClientRequest)) part, make sure to return req.close()
Make sure the URLs in addCredentials and getUrl match.