When OIDC authentication request is being validated, first readirect_uri and client_id are verified (client must be registered and it must allow specified redirect uri). After redirect_uri is verified all further validation errors should be redirected to redirect_uri with error/error_description parameters (for example "https://example.com/oauth-callback?error=invalid_request").
However there is response_mode param which tells how response (including error response) should be returned to the client. There are some scenarios in which response_mode is present in the authentication request but it cannot be verified/validated:
response_mode is just invalid / unsupported by server - in theory error response with error=invalid_request should be returned to the client afaik, but which response mode should be used in this case? some default response mode for authorization flow represented by response_type?
response_type is invalid/unsupported by server or not allowed by client - in this case error response with error=unsupported_response_type|unauthorized_client should be returned afaik, but which response_mode should be used in this case? The problem is that some response modes are not allowed by some authorization flows (for example response_mode=query in implicit flow). So for example if request contains response_type=invalid&response_mode=form_post, then how error response should be returned to the client? Using form_post?
response_type=token&response_mode=query - this is not allowed, but how error response should be returned to the client? Using query or fragment response_type?
I could not find in OAuth2/OIDC RFCs how to handle those cases. It seems reasonable to:
if response_type is invalid then use fragment response_mode to return error
if response_type is valid but response_mode is invalid or not allowed by client then use fragment response_mode to return error
if response_type is valid and response_mode is valid and allowed by client then, for any further request validation errors, use specified response_mode to return those errors to the client
But not sure, are there any documentation / best practices how OAuth2/OIDC server should behave is such cases?
I am trying to secure my web api (.net core 2.2) with Azure Ad using implicit flow.
I registered my application in Azure AD using the Azure Portal > Azure Active Directoy > App Registrations > New Application Registration:
Name = MyWebApi
Application Type = Web app / API
Sign-on URL = http://localhost:55000
Once this app is created, I opened its Manifest file and changed oauth2AllowImplicitFlow from false to true.
Thats all I did for the app registration in azure portal.
Then I called the following URL manually from my chrome browser to get access_token:
https://login.microsoftonline.com/MY-AD-TENANT-GUID/oauth2/v2.0/authorize?client_id=MY-REGISTERED-APP-GUID&response_type=token&redirect_uri=http%3A%2F%2Flocalhost%3A55000&scope=openid&response_mode=fragment
the response from calling the above url is:
http://localhost:55000/#access_token=MY-ACCESS-TOKEN&token_type=Bearer&expires_in=3600&scope=profile+openid+email+00000003-0000-0000-c000-000000000000%2fUser.Read&session_state=b2be972a-cfbc-49f1-bfc0-6c93f6c87d02
when I pass MY-ACCESS-TOKEN as Bearer token in Authorization header to my Web API (.net core 2.2) I get the following exception:
Microsoft.IdentityModel.Tokens.SecurityTokenInvalidSignatureException: IDX10511: Signature validation failed. Keys tried: 'Microsoft.IdentityModel.Tokens.X509SecurityKey , KeyId: N-lC0n-9DALqwhuHYnHQ63GeCXc'.
I then tried manually verifying the signature:
when I paste MY-ACCESS-TOKEN in https://jwt.io/ the header is:
{
"typ": "JWT",
"nonce": "AQABAAAAAACEfexXxjamQb3OeGQ4Gugvm6YdOT-bkA0IPllKMt06-J8If5AQ075TVCav94X_ZYcEYKaPneqdJcqYry-Z4XjX0eMN_fiJX_8wXe9D2b6eRiAA",
"alg": "RS256",
"x5t": "N-lC0n-9DALqwhuHYnHQ63GeCXc",
"kid": "N-lC0n-9DALqwhuHYnHQ63GeCXc"
}
I then went to this URL to obtain the public key for kid: N-lC0n-9DALqwhuHYnHQ63GeCXc
https://login.microsoftonline.com/common/discovery/keys
I then pasted the following as a public key on jwt.io to validated token signature:
-----BEGIN CERTIFICATE-----
OBTAINED-PUBLIC-KEY-FROM-THE-ABOVE-URL-HERE
-----END CERTIFICATE-----
and I again get Invalid Signature.
I have been to this thread: https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/609, but I am not sure why does my token header has nonce value or if this is an issue at all in my case or not.
Any ideas what I am doing wrong here?
I tried this on my side, it worked well.
Request url:
https://login.microsoftonline.com/tenant-name/oauth2/v2.0/authorize?client_id=application_id&response_type=token&redirect_uri=https://snv2app.azurewebsites.net&scope=api://f3d966c0-517e-4e13-a5bb-9777a916b1a0/User.read openid&response_mode=fragment
And when I got the access_token, I parsed it in the jwt.io and entered the public key, I got the result:
What is happening here is the token you are receiving is an access_token for the userInfo endpoint. The audience is graph. Tokens for graph have been modified in a special way so that they must be transformed before the signature can be validated. This allows for graph to forward the token downstream (after transforming) and not worry about a forwarding attack to occur.
To validate see if 'aud == graph'.
We're having a Keycloak with the realm socialBetaTest when I try to initate the Client Initiated Account Linking with the following URL (link with twitter):
https://socialBeta.maio290.de/auth/realms/socialBetaTest/broker/twitter/link?client_id=frontend&redirect_uri=https://localhost:4200/&nonce=someString&hash=someHash
I am getting the following error in my KeyCloak stdout:
WARN [org.keycloak.events] (default task-42) type=CLIENT_INITIATED_ACCOUNT_LINKING_ERROR, realmId=social, clientId=frontend, userId={properUserID}, ipAddress=x.x.x.x, error=invalid_token, redirect_uri=https://localhost:4200/, username={someEmailAddress}
What I notice here, they realm isn't the proper one, why is it called "social" and not "socialBetaTest"? And why is the token invalid, when it was issued (iss in the JWT) by socialBetaTest? Since we don't provide the token by any parameter, I guess it's reading the token out from the cookie and/or local storage.
Does anyone know how to fix this issue?
So, I have a ruby on rails project, I'm using the google-api gem and I'm trying to download a file from an account that I previously gave permission to my project to access and manage my google drive files. I have the refresh token and the access token and for some time, the download works fine. For some reason, after the access_token expires, even after I request a new one from the API using the refresh (which does work), the download request returns a 403 error with no information whatsoever about what 403 error it is.
First: why, after refreshing the access_token, am I still getting the 403 error?
Second: why is the response not returning any information about the error?
Fyi, if I go to my account, de-authorize the app and then authorize it again through my app, the download works fine again.
I really need help, since this kinda breaks my whole project if it doesn't work.
Edit: Tried again to see if the problem was still happening. I deleted my account yesterday, gave permission again to manage files and it worked until the access_token expired. After that it gives the 403 error message, even after using the refresh token to update the access one. Below is what I get from client.execute (with the client key and secret edited):
Response from Google API: #"16653014193614665626", "e"=>"download", "gd"=>"true"}, #headers={"User-Agent"=>"google-api-ruby-client/0.7.1 Linux/3.13.0-24-generic\n (gzip)", "Accept-Encoding"=>"gzip", "Content-Type"=>""}, #api_method=nil, #authenticated=nil, #authorization=#https://accounts.google.com/o/oauth2/auth>, #token_credential_uri=#https://accounts.google.com/o/oauth2/token>, #expiry=60, #extension_parameters={}, #additional_parameters={}, #client_id="***.apps.googleusercontent.com", #client_secret="***", #scope=["https://www.googleapis.com/auth/drive", "https://www.googleapis.com/auth/userinfo.email"], #access_token="***", #refresh_token="***">, #body="", #http_method=:get, #uri=#>, #response=# #request=# #request_headers={"User-Agent"=>"google-api-ruby-client/0.7.1 Linux/3.13.0-24-generic\n (gzip)", "Accept-Encoding"=>"gzip", "Content-Type"=>"", "Authorization"=>"Bearer *", "Cache-Control"=>"no-store"} #ssl=# #response_headers={"access-control-allow-origin"=>"*", "access-control-allow-credentials"=>"false", "access-control-allow-headers"=>"Accept, Accept-Language, Authorization, Cache-Control, Content-Disposition, Content-Encoding, Content-Language, Content-Length, Content-MD5, Content-Range, Content-Type, Date, GData-Version, Host, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, Origin, OriginToken, Pragma, Range, Slug, Transfer-Encoding, X-ClientDetails, X-GData-Client, X-GData-Key, X-Goog-AuthUser, X-Goog-PageId, X-Goog-Encode-Response-If-Executable, X-Goog-Correlation-Id, X-Goog-Request-Info, X-Goog-Experiments, x-goog-iam-role, x-goog-iam-authorization-token, X-Goog-Spatula, X-Goog-Upload-Command, X-Goog-Upload-Content-Disposition, X-Goog-Upload-Content-Length, X-Goog-Upload-Content-Type, X-Goog-Upload-File-Name, X-Goog-Upload-Offset, X-Goog-Upload-Protocol, X-Goog-Visitor-Id, X-HTTP-Method-Override, X-JavaScript-User-Agent, X-Pan-Versionid, X-Origin, X-Referer, X-Upload-Content-Length, X-Upload-Content-Type, X-Use-HTTP-Status-Code-Override, X-YouTube-VVT, X-YouTube-Page-CL, X-YouTube-Page-Timestamp", "access-control-allow-methods"=>"GET,OPTIONS", "date"=>"Wed, 20 Aug 2014 13:13:22 GMT", "expires"=>"Wed, 20 Aug 2014 13:13:22 GMT", "cache-control"=>"private, max-age=0", "server"=>"UploadServer (\"Built on Aug 12 2014 13:30:28 (1407875428)\")", "content-length"=>"0", "content-type"=>"text/html; charset=UTF-8", "alternate-protocol"=>"443:quic", "connection"=>"close"} #status=403>>>
After analysing the response while looking for things to hide (like the access_token), is it possible that the "access-control-allow-methods" paramater having the date and expires date the same is the issue here?
It seems the downloadUrl is directly connected to the access token. By storing the downloadUrl with the first access to the file's metadata and using the same downloadUrl with a new access token, the API was returning a 403 error. By requesting a new downloadUrl everytime a new token is requested as well, it works perfectly.
The 403 error means that you don't have the required rights, in this case, you are trying to use an expired token, this sounds like you have a problem with your cookie policy, change your cookie policy to none and let us know if the problem goes away.
Happy coding
I am having trouble with getting SWT Token validated with following code and throws error on line 3
Line 1: var managementUri = ServiceBusEnvironment.CreateServiceUri("https", <myServiceBusNameSpace>, string.Empty);
Line 2: var tokenProvider = TokenProvider.CreateSharedSecretTokenProvider(<...issuerName...>, <...issuerSecret...>);
Line 3: var namespaceManager = new NamespaceManager(managementUri, tokenProvider);
Here is the error:
The token provider was unable to provide a security token while accessing ......-sb.accesscontrol.windows.net/WRAPv0.9/. Token provider returned message: 'Error:Code:401:SubCode:T0:Detail:ACS50009: SWT token is invalid.:TraceID:d56b987a-90f4-4c20-8de1-9e2d55107e6c:TimeStamp:2013-08-30 13:56:52Z'.
I passed Service bus Shared Access Key Name and Shared Access Key as issuer name and issuer secrete but same error
I also passed ACS Service Identity Name and symmetric key as issuer name and issuer secrete but same error
I have no clue as why token is not validated. There is hardly any help from Microsoft site on this issues. I looked at ACS error code on MSDN and no help on this issue
I also configured BizTalk Receive location with sb connection string and has the same issue
I appreciate help on this issue and what could be the root cause of this error
Linesh,
The above API is only applicable for use with the ACS service identity and symmetric key. Based on the error it is likely a change is needed to the following line of code:
ServiceBusEnvironment.CreateServiceUri("https", <myServiceBusNameSpace>, string.Empty);
Can you replace "https" with "sb" and give it a try?