I'm writing my own codes for the OpenID Connect protocol. Basically, I intend to write my own provider and related stuff on Google App Engine's platform using Jersey and Google's datastore via Objectify library.
I'm in the middle of implementing the (access/refresh) token endpoint and there's this client authentication that I need to take care of. I'm just wondering if there are preset authentication schemes' keywords that I could send if in case the client did not have client_secret_basic set during the registration process (or whatever's set in the datastore entry.)
For a failed client authentication with the following methods, the scheme is used as response in the WWW-Authenticate header (401):
client_secret_basic: Basic,
client_secret_post: ???,
client_secret_jwt: ???,
private_key_jwt: ???,
none: obviously none.
I've looked at some open source implementations, nimbus' and OAuth-Apis', but they don't seem to handle this minor issue (they only respond with the generic error response defined in OAuth2 rfc6749#section-5.2.)
If there are no predefined keywords, then I suppose I'll have to make up my own. But it would be great if they exist.
The authoritative list for these is at IANA. There, you can find these handfuls:
Basic
Bearer
Digest
HOBA
Mutual
Negotiate
OAuth
SCRAM-SHA1
SCRAM-SHA-256
vapid
Which of these is client_secret_post, client_secret_jwt and private_key_jwt? None. You'll need to map those to one from the registered list above or return your own values. Better yet, you can submit a draft to the OAuth working group or the OpenID Foundation to get the above IANA registry updated with something that makes sense for these missing cases. Then, we can all interop :-)
Related
I have a default Spring authorization Server implementation. i want to modify it as per my project requirements.
I want to implement customized introspection endpoint in new spring authorization server.
I will be having different kinds of tokens, based on token type I want to validate them differently.
So I found out by default spring authorization server uses 'OAuth2TokenIntrospectionEndpointFilter', is there a way to use this class or we have to write a new class and add it to server configuration?
Thank you.
I tried doing the following.
authorizationServerConfigurer.tokenIntrospectionEndpoint(
t -> t.authenticationProvider(customTokenAuthProvider)
.introspectionResponseHandler(successHandler));
I want to know if this the right way to do or any other method exists.
It seems you have two goals:
Customize a jwt, by adding custom claims.
Obtain those claims via the introspection endpoint from a resource server.
There is actually nothing to code for on the authorization server side to achieve #2, as the introspection endpoint returns all claims for a jwt by default. I’m not clear on what you mean by “validate” here, so I’m assuming you mean validate the token and then obtain claims from it. This is what the introspection endpoint does, no customization required. Do note however that the introspection endpoint is not usually called if the resource server is decoding the jwt locally. This would only happen if the resource server is treating the token as opaque.
In order to achieve #1, simply provide an OAuth2TokenCustomizer #Bean as demonstrated in the reference documentation.
Note: I don’t see a need for a custom AuthenticationProvider. If you feel you do have a need for one, then I think some details of your use case are missing.
I am struggling to access the Dynamics 2016 CRM OData Web APIs from a console application.
We have Dynamics CRM 2016 installed, configured with Claims-based authentication, and using AD FS v3.0.
My understanding is that a console app (or web app) should be able to access the Web APIs using Windows integrated authentication (i.e. NTML or Kerberos) without any special treatment ... or maybe the OAuth flow should work when enabled.
For a regular user accessing Dynamics "pages", the authentication works fine (redirection to AD FS log in page), but accessing the OData APIs does not seem to work (for instance : https://crm.domain.org/api/discovery/v8.0/ ) :
in a browser I get a Windows login prompt and typing valid credentials always results in a HTTP 401 unauthorized error
in a brower, if I navigate to a Web API url after having logged on on the pages , then I can access the Web APIs (i.e. some cookies must be set and I am already implicitly authorized)
from code, using an HttpClient with specific valid credentials (or current credentials) , I also get a 401
Things I have tried :
if I disable Claims-based authentication completely , HttpClient works fine and I can access the OData APIs
if I leave Claims-based authentication enabled, and activate OAuth via PowerShell Add-PSSnapin Microsoft.Crm.PowerShell ; $ClaimsSettings = Get-CrmSetting -SettingType OAuthClaimsSettings; $ClaimsSettings.Enabled = $true ; Set-CrmSetting -Setting $ClaimsSettings ;.
Windows integrated authentication still does not work, but using Bearer authentication is now possible. I can use this snippet to retrieve the OAuth Endpoint for token generation, and use AuthenticationContext.AcquireTokenAsync to issue a token, and then pass it in the Authorization HTTP Header ... but then, no matter what, I get this error :
Bearer error=invalid_token, error_description
=Error during token validation!, authorization_uri=https://our.adfs.domain.org/adfs/oauth2/authorize, resource_id=https://crm.domain.org/
Am I missing something ? is that possibly a configuration issue ?
From this answer from the dynamics community forum, it looks like the api is pretty strict about the parameters and headers it requires. When doing the request, make sure you have the Cache-Control: no-cache and Content-Type: application/x-www-form-urlencoded headers set.
In the subsequent request to access the api with the retrieved token you should set the Authorization header in the form of Bearer: TOKEN (worth noting since a lot of people actually thought they could directly put the token), the OData-Version: 4.0, Cache-Control: no-cache and Accept: application/json ones too.
Looking at the different OAuth endpoints and the previously linked answer, I'm not sure the authorization uri is the right one (eg https://login.windows.net), so do you make sure that's correct. It's also stated that you should use the OAuth endpoint url and use the WWW-Authenticate header that returns the valid one, even if this route will respond with a 401. I'm sure you already saw this example, but it provides a pretty complete overview of an auth flow and how the token is retrieved using AcquireTokenAsync where you pass your resource and clientID. I might also be looking at an updated page and it's not relevant in your case.
You also want to check if the resource id you specified is the correct one, some people reported to have to specify one in the form of https://crm3.domain.org/ or https://crm4.domain.org/ instead of the bare one, so that could be one thing.
It could also be a configuration issue, given what #l said about the fact an IP would work instead of the domain name. It could very well be a certificate problem, where it's not validated correctly or untrusted, thus creating the error you see even if it's not the appropriate message. Also make sure your 443 port is allowed through your firewall(s).
One interesting post where the author explains that the Form Authentication setting of the AD FS Management Console was required for him to proceed (it's CRM 2013, but might still be related).
I'm trying to add OTP/2FA support into OAuth2, but after much reading through the RFC6749, it's still not clear how OTP/2FA could be cleanly added without violating the specification.
Although OTP/2FA entry can be added into the authorize dialog flow, there is no provision for adding it into token. For example, public client apps with Resource owner password-based privileges may want to provide the token directly when requesting a new access_token, rather than having to embed a HTML dialog box.
Therefore my questions are;
Does the RFC allow for custom grant_type? Should this be used to provide 2FA/OTP functionality?
Does the RFC allow for additional attributes on an existing grant_type? For example, grant_type=token&otp_code=1234 (RFC does not make it clear if additional attributes are allowed on grant_type's within the specification)
Should OTP functionality be placed into headers? This is the approach that Github used, but it feels really ugly/hacky.
Are there any other approaches that I have overlooked?
Thank you in advance
The RFC allows for an extension (custom) grant, see section https://www.rfc-editor.org/rfc/rfc6749#section-8.3. That grant could define additional attributes.
OAuth 2.0 does not define how the Resource Owner authenticates to the Authorization Server, with the exception of the Resource Owner Password Credentials grant. Your proposal could be designed as an extended variant of that grant.
I'm working on something similar. I've got an endpoint at which you can request certain metadata for a user such as whether or not 2fa / mfa / otp is turned on and the salt (and iterations and algorithm) for Proof of Secret / Secure Remote Password.
If you go that route you can simply extend the grant types with an mfa or totp field (that's what I'm doing). You could also create a custom grant type as mentioned above (perhaps more proper).
Another solution is to check for MFA / 2FA / OTP during the authorization dialog step.
If I were done with my OAuth2 implementation I'd link you to that code too, but here are some libraries for an Authenticator:
Browser Authenticator has the components you need to generate and verify a key and token in the browser: https://git.coolaj86.com/coolaj86/browser-authenticator.js
Node Authenticator has the complementary server-side code: https://git.coolaj86.com/coolaj86/node-authenticator.js
You would still need to provide your own database storage mechanism and link it in to your OAuth implementation or you could make a very simple one and run it as a microservice.
I agree with Hanz Z.: you can design your own grant type to consume OTP.
But OTP can also be used for client authentication (confidential clients as you have to store credentials).
For example, we could imagine an header in the token request (X-OAuth2-OTP = 01234567). Client authentification will fail if the client activated OTP but no header is set.
Based on specifc SCOPE (Ex. OTP) you can mark bearer(access_token) as ""verified_otp = false"" on the backend, then after authorization server received valid otp for that session mark your bearer(access_token) as ""verified_otk = true"". For your resource server, check verified_otk field befores authorize calls that depends this verification.
I feel silly even asking this question, but am at the limits of my understanding, and am hoping someone can provide some context.
I'm looking at the following (https://stormpath.com/blog/token-auth-for-java/) which states:
The access_token is what will be used by the browser in subsequent requests... The Authorization header is a standard header. No custom headers are required to use OAuth2. Rather than the type being Basic, in this case the type is Bearer. The access token is included directly after the Bearer keyword.
I'm in the process of building a website, for which I'll be coding both the back-end REST service, as well as the front-end browser client. Given this context, why do I need to follow any of the guidelines given above? Instead of using the access_token, Authorization and Bearer keywords, what's stopping me from using any keywords I like, or skipping the Bearer keyword entirely in the header? After all, as long as the front-end and back-end services both read/write the data in a consistent manner, shouldn't everything work fine?
Are the keywords and guidelines given above merely best-practice suggestions, to help others better understand your code/service? Are they analogous to coding-styles? Or is there any functional impact in not following the above guidelines?
Given this context, why do I need to follow any of the guidelines given above?
Because they are standardized specifications that everyone is meant to conform to if they want to interact with each other.
Instead of using the access_token, Authorization and Bearer keywords, what's stopping me from using any keywords I like, or skipping the Bearer keyword entirely in the header?
Nothing, except that it won't be OAuth anymore. It will be something custom that you created for yourself that noone else will understand how to use, unless you publish your own spec for it.
After all, as long as the front-end and back-end services both read/write the data in a consistent manner, shouldn't everything work fine?
Who is to say that you alone will ever write the only front-end? Or that the back-end will never move to another platform? Don't limit yourself to making something custom when there are open standards for this kind of stuff.
Are the keywords and guidelines given above merely best-practice suggestions, to help others better understand your code/service?
No. They are required protocol elements that help the client and server talk to each other in a standardized manner.
Authorization is a standard HTTP header used for authentication. It has a type so the client can specify what kind of authentication scheme it is using (Basic vs NTLM vs Bearer, etc). It is important for the client to specify the correct scheme being used, and for the server to handle only the schemes it recognizes.
Bearer is the type of authentication that OAuth uses in the Authorization header. access_token is a parameter of OAuth's Bearer authentication.
If you use the Authorization header (which you should), you must specify a type, as required by RFCs 2616 and 2617:
Authorization = "Authorization" ":" credentials
credentials = auth-scheme #auth-param
auth-scheme = token
auth-param = token "=" ( token | quoted-string )
So, in this case, Bearer is the auth-scheme and access_token is an auth-param.
Are they analogous to coding-styles?
No.
Or is there any functional impact in not following the above guidelines?
Yes. A client using your custom authentication system will not be able to authenticate on any server that follows the established specifications. Your server will not be able to authenticate any client that does not use your custom authentication system.
The Dropbox OAuth 2 requires me to set a return URL. Is it possible to implement the OAuth 2 flow with a dynamic return URL?
Background on why I need the return_url to be dynamic: The flow works great if the integration is through a website, however I am working on a product which is managed through a web console, and typically users will access it using the private IP on the unit. This IP is something I cannot know in advance.
Possible Solutions if dynamic return URLs aren't possible:
I host a cloud service of some sort to act as a broker --- the broker is a fixed URL and I relay back the access code to the device.
Use OAuth 1, which doesn't seem to have this restriction.
Florent's comment is correct, this isn't currently possible, as all OAuth 2 redirect URIs are required to be pre-registered as a matter of security. I'll be sure to pass this along as feedback though.
As mentioned though, one thing you may be able to do instead is to use one static redirect URI but encode the necessary information in the 'state' parameter, and decode it as necessary after the redirect back to your app, to handle it as necessary:
https://www.dropbox.com/developers/documentation/http/documentation#oauth2-authorize
Alternatively, you can use OAuth 1, which doesn't require pre-registered redirect URIs. Edit: note that OAuth 1 is only available for API v1, which is now deprecated.