I'm having a trouble in requesting a refresh token, it keep returning an Unauthorized 401 error. I don't know if I'm lacking a parameters that I passed when I did a request.
I added the doorkeeper configuration for refresh token.
use_refresh_token
Here's the request details:
{{root_url}}/oauth/token
{"refresh_token"=>"034a74c085219fb8297fd8ef9b59f080918f"
"format"=>:json,
"controller"=>"/oauth/tokens",
"action"=>"create",
"grant_type"=>"refresh_token",
"client_id"=>"<client_id>",
"client_secret"=> "<client_secret>"}
Error descriptions:
{:error=>:invalid_grant,
:error_description=>
"The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client."}
Btw, all of my api request authentication is not failing just this refresh token. I wonder what I'm missing in the request parameters.
Do not pass the client_id and client_secret.
The required parameters for the refresh token are:
grant_type
refresh_token
Optional parameter:
scope.
See the Refresh Token section of rfc6749: The OAuth 2.0 Authorization Framework
Related
I aim to fetch purchases from googleapis by using a service account on server-side.
Method: purchases.products.get api requires an oauth2 authentication.
Therefore I create an oauth2 token -from the client-secret.json I am provided from consolce.cloud.google- inside of my server-side backend java spring application.
GoogleCredentials googleCredentials = GoogleCredentials.fromStream(new FileInputStream("src/main/resources/client_secret.json")).createScoped("https://www.googleapis.com/auth/androidpublisher");
googleCredentials.refresh();
AccessToken accessToken = googleCredentials.getAccessToken();
The token I generate is like 'ya29.c.b0AXczHcuLszNI................'
It ends with multiple dots I don't know why.
https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/purchases/products/{productId}/tokens/{token}
After I get the token I do the GET request to this URL.
I gets the following error:
"message": "Request is missing required authentication credential.
Expected OAuth 2 access token, login cookie or other valid
authentication credential. See
https://developers.google.com/identity/sign-in/web/devconsole-project.",
Why my token is not working? The way I use it, Is it wrong? And/or oauth2 token generation way is it wrong?
The access token is sent as an authorization header. The access token should be prefexed with the term bearer as it is a bearer token.
I haven't seen a good explanation online as to the specific security exploit that this protects from.
Assuming the OAuth provider validates the redirect_uri in the initial call to the authorization endpoint, why then must the provider also validate the redirect_uri in the subsequent backchannel call to the token endpoint (auth code to token exchange)?
Even the spec only mentions Authorization Code Redirection URI Manipulation as a vulnerability that would be prevented by a check in the auth endpoint alone.
This explanation does not link to an actual vulnerability or exploit:
"As an added measure of security, the server should verify that the redirect URL in this request matches exactly the redirect URL that was included in the initial authorization request for this authorization code."
I use [JWT for Client Authentication][1] in [Keycloak][2]:
POST /token.oauth2 HTTP/1.1
Host: as.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&
code=vAZEIHjQTHuGgaSvyW9hO0RpusLzkvTOww3trZBxZpo&
client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3A
client-assertion-type%3Ajwt-bearer&
client_assertion=eyJhbGciOiJSUzI1NiJ9.
eyJpc3Mi[...omitted for brevity...].
cC4hiUPo[...omitted for brevity...]
I get :
assess_token
refresh_token
token_type
expires_in
When I try to refresh token I send refresh_token itself, grant type refresh_token and get:
"error": "unauthorized_client",
"error_description": "INVALID_CREDENTIALS: Invalid client credentials"
}```
when I specify `client_id` I get:
```{
"error": "invalid_client",
"error_description": "Parameter client_assertion_type is missing"
}```
If I specify `client_assertion_type` I get error that `client_assertion` itself is missing, so I literally have to provide parameters I provided when retrieved access token.
How that refreshing process actually should work?
[1]: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-jwt-bearer-12#section-2.2
[2]: https://www.keycloak.org
This could very well be a limitation or policy defined by Keycloak. RFC7523 (JWT for Client Authentication) does allow to enable client credentials when JWT authentication is present. This is highlighted from 3.1. Authorization Grant Processing
JWT authorization grants may be used with or without client
authentication or identification. Whether or not client
authentication is needed in conjunction with a JWT authorization
grant, as well as the supported types of client authentication, are
policy decisions at the discretion of the authorization server.
However, if client credentials are present in the request, the
authorization server MUST validate them.
So even if Keycloak support JWT client authentication, it may still require client credentials to be present in the refresh token request. But also, it could be a limitation from their end.
Additionally, token refresh is defined through RFC6749 - The OAuth 2.0 Authorization Framework. According to it's section 6, refresh token request must contain client credentials when client is a confidential client (simply a client which was created with id and a password). If what you seen is not a limitation, then guess Keycloak adhere to RFC6749 and require you to send client credentials in token refresh request.
I'm doing authorization with Azure AD (using /oauth2/v2.0/authorize) with these scopes:
openid email profile https://graph.microsoft.com/user.read
In response, I get an id_token and an authorization code. I ignore this id_token and use the authorization code to get an access token (using /oauth2/v2.0/token)
When I get the access token, I again get an id_token along with it.
The Microsoft docs state:
When your app receives an ID token, it must validate the signature to prove the token's authenticity and validate a few claims in the token to prove its validity.
But since my app received the ID token based on its own HTTPS post to a Microsoft server, is it safe to use the ID token without validating it?
According to what you have described,
You are using OpenID Connect
You are using the hybrid flow (with response_type=code id_token)
If you are not expecting an id token from authorization request, you can use use other either Authorization code flow or Implicit flow
These flow types are selected from response_type parameter and not from claims.
For authorization code flow,
response_type=code
For Implicit flow,
response_type=id_token token or response_type=id_token
Note that, implicit flow does not produce an access token and is intended for JavaScript or similar clients which cannot protect a refresh token.
Once you get the id token from the token endpoint or from authorization endpoint(based on implicit flow), you can validate it just once.
I am writing an API that uses the OAuth 2.0 password flow to authenticate users. When a request for an access token is denied, there does not seem to be any way for a client to tell whether the password was incorrect, or expired. From the spec, an error code of invalid_grant should be returned in both cases:
invalid_grant: The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.
Is it acceptable to use the error_description on the response to state that the password has expired so that the client can take the necessary action, and if not, what is the standard approach for handling password expiry with OAuth?
"Leaking" that the reason for such a failure such as "password was incorrect, or expired" is NOT a best practice for authentication.
I would suggest that the "server" log the reason for the failure and NOT return the information to the requestor.