I recently changed teams. This team is using a home grown Idp and I think I'm finding some serious issues with it. One issue stems from the Idp allowing auth codes to be retried in the token request endpoint if the original token request contains bad data. For example lets say this is allowed:
Post Request 1:
my-idp.com/token
body:
client_id: "K0VnRAenS1ANsmZvd0z3e512414"
client_secret: "guess1"
grant_type: "authorization_code"
code: "yAVNDcXq12fas"
redirect_uri: http://facebookforcatz.com
It returns a 400 because let's say the client_secret is really "my-secret" but when the caller gets the 400 it can immediately try again with this post request:
Post request 2:
my-idp.com/token
body:
client_id: "K0VnRAenS1ANsmZvd0z3e512414"
client_secret: "my-secret"
grant_type: "authorization_code"
code: "yAVNDcXq12fas"
redirect_uri: http://facebookforcatz.com
this time request 2 returns an access token. Isn't this a significant attack vector? Shouldn't the second request return an error response and no access token because the auth code was used in the first post request?
I'm trying to determine how big of an issue I raise with management. It sure seems like we're violating this portion of the RFC:
https://www.rfc-editor.org/rfc/rfc6749#section-4.1.2
In particular it seems we're violating this:
The client MUST NOT use the authorization code more than once. If an
authorization code is used more than once, the authorization server
MUST deny the request and SHOULD revoke (when possible) all tokens
previously issued based on that authorization code.
Are we violating the RFC's requirements around code reuse or are we meeting the standard because the first request failed, therefor the code wasn't "used"?
On top of this "re-use" issue redirect_uris aren't being whitelisted at all so we could send auth codes to sites that attempt to brute force the secret.
Related
I'm having trouble to allow users to logout from an application that uses Keycloak for access management.
I have found this topic being discussed here and there, but not clear instructions on how to handle the logout.
I tried to cause the logout of an user redirecting the browser to an endpoint of the following format:
https://example.com/auth/realms/myrealm/protocol/openid-connect/logout?id_token_hint=mytoken&post_logout_redirect_uri=https://example.com/initialpage/
What I used as "mytoken" was the access_token I had obtained making a post request to the endpoint:
https://example.com/auth/realms/playipintern/protocol/openid-connect/token
passing to it parameters like the ones bellow:
grant_type="authorization_code"
code=code_obtained_from_a_url_to_which_keycloak_redirected_the_browser
client_id=client_id_created_using_key_cloak_gui
redirect_uri=the_to_which_keycloak_redirected_the_browser
and reading the body of the response. The content of the body was a json, like the one bellow:
{
'access_token': 'long_token_I_used_latter_as_token_hint_trying_to_logout',
'expires_in': 300,
'refresh_expires_in': 1800,
'refresh_token': 'other_long_token',
'token_type': 'bearer',
'not-before-policy': 0,
'session_state': 'a_shorter_code',
'scope': 'email profile'
}
My logout attempt resulted in the following message in Keycloaks log:
22:53:51,686 WARN [org.keycloak.events] (default task-24) type=LOGOUT_ERROR, realmId=playipintern, clientId=null, userId=null, ipAddress=192.168.16.1, error=invalid_token
and the response said "We are sorry, session not active".
Now I'm aware that I should have used the id_token and not the access_token to logout, but received no id_token in the json.
Somewhere, someone said I should have included
scope=openid
in the parameters that I used to obtain the token. I did it, expecting to find an "id_token" field in the json, but nothing changed.
Someone else reported to have needed to create a scope (I believe using Keycloak's GUI) named "openid" to obtain the token. That didn't make much sense to me, but I tried it anyway and added the just created scope to the client scopes using Keycloak's GUI again. Oncemore, the json didn't change.
I tried to use the refresh_token as the id_token, but that also resulted in an invalid token message.
I don't know what to try now. Any help is appreciated.
Thank you.
/token endpoint returns only the access token by default. No refresh token is returned and no user session is created on the Keycloak side upon successful authentication by default. Due to the lack of refresh token, re-authentication is required when the access token expires. However, this situation does not mean any additional overhead for the Keycloak server because sessions are not created by default.
In this situation, logout is unnecessary. However, issued access tokens can be revoked by sending requests to the OAuth2 Revocation Endpoint as described in the OpenID Connect Endpoints section:
/realms/{realm-name}/protocol/openid-connect/revoke
Example:
POST /revoke HTTP/1.1
Host: server.example.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
token=45ghiukldjahdnhzdauz&token_type_hint=access_token
You need to put your token in place of 45ghiukldjahdnhzdauz.
token_type_hint can take either access_token or refresh_token as value to define which type of token you want to revoke.
You will have to add scope=openid to your initial request to http://example.com/auth/realms/playipintern/protocol/openid-connect/auth (note the /auth instead of /token at the end) before the redirect from where you copied the access code.
You can find further information and explanation in this article.
We have an inquiry from our client, to enable Autodesk Model Viewer from within our App. The first step is to implement OAuth2 authentication (2 legged). I followed Forge Autodesk tutorials, but this is completely new to me, and I cannot configure that to work. I do http request (using jQuery) from our App, passing client_id and client_secret, grant_type and a scope. When looking on the developer menu (F12) - I can see that request is hitting their server and returns with the access_token, expire time, authorization "Bearer" with the status 200. So far so good.
I understand that now I need to make a call back to the API and pass this access_token I received. And here is where I lost: console shows me error, Cross origin ... And the success part of http request is not fireing (in http request success part I'm trying to redirect user to the Model Viewer url + access_token we just received). But it is never fires. Was digging forums and tutorials but can't find any good sample or explanation what I'm doing wrong. Below is my code example:
$.post("https://developer.api.autodesk.com/authentication/v1/authenticate",
{
client_id: 'here_is_a_client_id',
client_secret: 'here_is_a_client_secret',
grant_type: 'client_credentials',
scope: 'viewables:read'
},
function(data, status){
console.log("Data: " + data);
window.location.href = 'https://viewer.autodesk.com/id/here_is_a_long_id_number&Authorization=Bearer&' + data;
});
Any help highly appreciated. Also, I was trying to follow Autodesk tutorials using Node.js, but again, after seeing that access_token get back from their server, can't make a callback and attach this access_token to it. New to all these Authorization/Authentication/Tokens so can't figure out the way it works. Thanks in advance.
I could advice you how to avoid this Cross Origin error, but it is critical not to and very dangerous to authorise your application on the client side. Exposing you client secret key will give everyone the right to access your account and spend cloud credits on your behalf. And access all your content. That is the reason you do should not have that approach.
You should never expose the client secret, neither an read/write scoped access token on a client, those should resides on the server, and server only. The only access token you could eventually see on the client should be a viewables:read scoped token only. And even when using a viewables:read token, I prefer to use a proxy instead myself (see here).
I allow users to authorize their Microsoft accounts using oAuth and the Microsoft Graph API. I am using this omniauth strategy to facilitate the authorization. In the OmniAuth strategy, it includes the resource for both authorize_params and token_params "https://graph.microsoft.com". This allows me to authenticate just fine but when I go to refresh the auth, I get this error returned:
{"error"=>"unauthorized_client", "error_description"=>"AADSTS70001: Resource 'https://graph.microsoft.com/' is not supported as resource.\r\n"}
Along with a trace_id and some other things that I will post if needed.
The endpoint I am hitting to refresh is POST https://login.microsoftonline.com/common/oauth2/v2.0/token with the client_id, refresh_token and grant_type: "refresh_token" params.
Refreshing this oAuth token was working fine as recently as last week. Did something change with the Microsoft Graph API or something?
You may want to take a look at Refreshing a Token.
It sounds like you were partially there, you were just missing some additional parameters:
grant_type - Set as refresh_token
refresh_token - The refresh token value you received from the Provider
client_id - This is your Application ID from above
client_secret - This is the Password we generated before
scope - This should match the same set of scopes you first requested
redirect_uri - This is the redirect URI defined in your application registration
These are formatted application/x-www-form-urlencoded in you POST to https://login.microsoftonline.com/common/oauth2/v2.0/token
POST URL: https://login.microsoftonline.com/common/oauth2/v2.0/token
POST HEADER: Content-Type: application/x-www-form-urlencoded
POST BODY: grant_type=refresh_token&refresh_token=[REFRESH TOKEN]
&client_id=[APPLICATION ID]&client_secret=[PASSWORD]
&scope=[SCOPE]&redirect_uri=[REDIRECT URI]
Turns out it was as simple as I was authing to v1.0 but attempting to reauth to v2.0. Not sure why this worked up until now but ensuring they are hitting the same version of the API has solved the issue.
I have a hobby project in mind to use battle.net login. I'm wondering how I can obtain the access token from the API after receiving the authorization code.
This is Oauth flow question rather than a battle.net question.
Currently I can successfully authorize the user for my app which is registered in dev.battle.net and then I try to use the authorization code returned from the battle.net login to obtain the access token by sending a request to https://<region>.battle.net/oauth/token.
However I keep receiving this error:
{
"error": "unauthorized",
"error_description": "An Authentication object was not found in the SecurityContext"
}
I use postman extension to send post requests to that uri. I authenticate my request with my client id and secret. I pass redirect_uri (https://localhost), granty_type (authorization_code), code(the code returned from the previous authorization step). However I keep getting the error above.
I couldn't find much about battle.net online. There are other oauth related help articles but couldn't really find my way.
Wondering if you can help me with this easy stuff. I'm just wondering what I'm skipping here.
Here is the documentation:
https://dev.battle.net/docs/read/oauth
https://localhost is added in my mashery dev account's app settings.
Me again, I resolved this problem after trying almost every combination in the universe:)
Steps to apply:
Don't use the same authorization token for different access token trials, they are not valid
Always use https on every domain you test including localhost, you
redirect_uri must be https as well.
You must use the "basic authentication" in the header of your POST request while requesting the token from the authorization code you obtained from the previous step.
This is one of the most important ones: For requesting token, Pass redirect_uri, client key and secret as POST form parameters to the authenticated request. This is interesting because it's already an authenticated request; why would i need to pass my secret again? Anyways, that's how it works.
Here are the full text:
http://hakanu.net/oauth/2017/01/26/complete-guide-of-battle-net-oauth-api-and-login-button/
This is working prototype:
https://owmatch.me
Thanks.
I am getting the following error when I use the linkedin V1 API:
response body: {
"errorCode": 0,
"message": "[unauthorized]. The token used in the OAuth request has been revoked. 75--5cfb9cdb-3c9c-47c2-b3f8-XXXXXXXX",
"requestId": "I2GQ0ZMWIE",
"status": 401,
"timestamp": 1408976297742
}
I am using this guide here, I am doing exactly what this person is doing but I get a different result:
https://github.com/PrincessPolymath/LinkedIn-OAuth-Sample-Client
I have no idea why I get The token used in the OAuth request has been revoked. for an error. The HTTP request is identical. Could it be something with my bundle ID?
I cannot find anything from linkedin on the matter. Why don't linkedin have normal error-code lookups like other API's.
Here are some photos of the two request objects, one from the example and one from mine.
I'm taking a guess here based on my understanding of the problem you're describing, have not tested this. I'm also assuming you got your credentials right...
You should checkout this answer by Kamyar Mohager (#39), he explains how to bypass this error:
When obtaining access token, error occurs if:
POST https://www.linkedin.com/uas/oauth2/accessToken
Body:
{
grant_type=authorization_code,
code={auth-code},
redirect_uri={uri},
client_id={id},
client_secret={secret}
}
The error WON'T occur if you obtain the access token by passing the params as query params:
POST https://www.linkedin.com/uas/oauth2/accessToken?grant_type=authorization_code&code={auth-code}&redirect_uri={uri}&client_id={id}&client_secret={secret}
Error clearly states that the user is authorized to make a call using the token which you are using.
"message": "[unauthorized]. The token used in the OAuth request has been revoked. 75--5cfb9cdb-3c9c-47c2-b3f8-XXXXXXXX",
In the two photos which you pasted above I can see that your request object has different values "tokenKey and tokenSecret" parameters than the example request object, which is correct as your request should have the token information which received from LinkedIn.
But the thing which I don't understand is why both the request objects have same values for "consumeKey & consumerSecret" parameters. I think you need to use your "consumerKey & consumerSecret" with your "tokenkey & tokensecret" to make this OAuth call. "consumer" and "token" detail combination should match then only you will be allowed to make the successful oauth call.
I guess you saw this error because you used your token with some other consumer key.
One more thing I can see that you are passing the "verifier" in your request object hence I want to know are you making a call to get the "access token" which is a 3rd leg of oauth. If yes then there could be scenario that "requestToken" is getting expired before you are making this "access_token" call as "requestToken" is actually a "temporary token" and expires quickly.
HTH...
The issue was code re-use.
As stated in the comments for the API, the API will give you a token and secret upon the first request. This only happens during authentication and then the token and secret can basically be thrown away, and the one issues at developer.linkedin can be used.
I fixed this by constructing my own request object rather than relying on the old HTTPRequestBody in the oAuth process.