I have a question regarding the auth-scheme. I stumble across JSON Web Tokens and one of the official page:
https://jwt.io/introduction/
They use
Authorization: Bearer <token>
In the past, I am familiar with the Authorization: JWT <token> and had assume that was correct until today, I read the official JWT webpage and they used Bearer <token> instead.
I was testing the Knock Rails gem: https://github.com/nsarno/knock and with this library, I was able to make a Postman request to my Rails API with random auth-scheme:
I could even get rid of the auth-scheme completely:
When I remove my JWT token from the Authorization header, however, it returns 401 Unauthorized response as expected, so I know it's...working?
So I began to think...is there a purpose to the auth-scheme ?
Is a library or web server suppose to honour/respect/enforce the correct usage of auth-scheme in the Authorization header?
I came across this Stackoverflow post in my quest for answer:
Custom HTTP Authorization Header
It showed the official format is:
credentials = auth-scheme #auth-param
The example given was even more bizarre:
Authorization: FIRE-TOKEN apikey="0PN5J17HBGZHT7JJ3X82", hash="frJIUN8DYpKDtOLCwo//yllqDzg="
I don't know if this qualifies as a programming question. I can blindly follow/use a third party library.
What's the purpose of the auth-scheme ?
I'm no cryptography/computer security expert.
Maybe someone can shed some light on the issue (or maybe non-issue?) ?
The authorization scheme is just an indication to the server of what type of credentials are following. A client can use basic scheme
Authorization: Basic <base64(username:password)>
Or bearer scheme
Authorization: Bearer <base64(JWT)>
Or the Hawk scheme
Authorization: Hawk id="...", ts="...", nonce="...", ext="...", mac="..."
Or any other scheme it can agree on with the server.
Related
I have 2 internal Rails services, which need to speak to each other.
I need an advice how to make it secure enough and with minimum effort.
Currently service A sends Authorization HTTP header to service B, which contains secret token. Simple HTTP Token-based method, nothing special. But I also need somehow to communicate a user token, so service B will know, which user is talking to it.
My current solution is following:
send Authorization Token token=blabla user_token=blabla2
use existing in Rails methods to parse it
identify user by provided user_token
inspired by this StackOverflow post
Alternatives:
Amazon way with something like: Authorization: MY-APP-V1 Token=blabla Credential=user_token, but I need custom parser for it.
Custom HTTP header like X-USER-TOKEN, but seems like RFC is not in favor of this idea.
Your proposal or suggestion
Thank you very much for any help.
I'm curious as to why the user token is not enough, can you elaborate on this?
But assuming you want to continue with the double-token approach, something like JWT could be used to encode the user token with the secret token. That way you will just have 1 token and can send it simply as Authorization: Bearer xxxxxx.
I'm a newbie to this stuff so downloaded the samples which is all fine and I thought I could see what was going on and what I needed to do. However, got a bit stuck for no obvious reason so I wondered if anyone could maybe give me some hints.
I'm trying to engineer Cognito authentication and identity into an old Apache Struts 1 legacy web application written in Java, so all the activity needs to be server-side. Using the Cognito https://xxx.auth.xxx.amazoncognito.com/login? URL I can successfully authenticate and get an auth code back using this URL providing my client id, redirect URI and response_type=code so all good thus far.
If I then create an HttpClient (as per the sample code in Github) and call the token URL https://xxx.auth.xxx.amazoncognito.com/oauth2/token and write various parameters to the request body (grant_type=authorization_code, client_id=as previously, redirect_uri=my URI and code=auth code just returned), I get an "unauthorized_client" message returned. But the code is valid albeit for authorization, and the client_id is correct because I used it previously.
My log:
Cognito following successful signin, continuing to url http:[redacted]/passport/CognitoHandlerSignIn.do?code=62eeb0b1-a76b-489b-bd28-e42023a497bd
(this was the /login succeeding)
Callback from Cognito received
(following is the log dump of the /oauth2/token URI called to)
Cognito token signin URL is https:[redacted].amazoncognito.com/oauth2/token
HTTP request header, added Authorization=Basic M29wcGR0azdpYzF2YjloNGd0OTQzNXYxcmI6MW9mMmFsaWNzZGR2dHZ1NmFkOHRuc2s4cnJ0cXEyYm0yc3RqbG1mcmkyamhkdXBubG1wMw==
HTTP request header, added Content-Type=application/x-www-form-urlencoded
HTTP request body, added grant_type=authorization_code
HTTP request body, added
redirect_uri=https%3A%2F%2F<redacted>%2Fpassport%2FCognitoHandlerSignIn.do
HTTP request body, added code=62eeb0b1-a76b-489b-bd28-e42023a497bd
HTTP request body, added client_id=[redacted]
HTTP request is sun.net.www.protocol.https.DelegateHttpsURLConnection:https:
[redacted].auth.eu-west-1.amazoncognito.com/oauth2/token
HTTP Json result=<{"error":"unauthorized_client"}>
org.json.JSONException: JSONObject not found.
at org.json.JSONObject.get(JSONObject.java:454)
at
What's wrong with this picture? I tried also adding client_id, code as URL parameters but I just get an "invalid_client" message instead.
I also tried using the /oauth2/token URI directly from the Struts app to provide a token but it returns the id_token using # rather than ? in the parameter list so it is client-side only and hence can't be intercepted by the Struts app and so will be a pain to forward to the server, but I could write some Javascript to do it if I had to. It doesn't seem the path of least resistance, though, as it seems wrong that the pure Java server side call doesn't work so I must be doing something wrong which isn't obvious to me.
I am adding JWT Auth for a completely new frontend to a legacy Rails backend.
Upon HTTP request, it seems most sources suggest I send the token back to the server via Bearer Header.
Why? What is the additional value of sending via header (bearer or basic). What can't I simply pass the JWT back to the server via .json and authenticate the token from there.
What benefit does an Authorization header give me, and moreso, what does a Bearer Authorization header give me?
I can of course simply follow everyone's example, but want to understand why. The bearer docs are verbose and hard to understand what I'm gaining over simple sending the JWT as part of the data in the request.
Thank you.
You can technically send a json body on each request with the JTW but that would be non standard behaviour (for instance, GET requests should not have a body via the spec).
A more standard way would be to provide an Authorization HTTP header.
The Authorization header is not specific to JWTs and its role is to specify an auth scheme between the client and the server.
Another way would be to include the JWT inside a cookie but that would make the behaviour browser specific while the HTTP header can be sent by virtually any HTTP client.
P.S
Bear in mind that contrary to Auth cookies which are sent by the browser automatically the Authorization header needs to be set by the client explicitly.
I just starting working on an iOS Swift 3 application that will integrate with a certain EHR. I had it working several months ago, but when I tried it this eve I noticed the application froze when I tried to get the access token. it appears that the token part of the OAuth2 exchange has changed and now looks like this:
POST https://api.xxxxxx.com/oauth2/access_token
curl -X POST https://api.xxxxxx.com/oauth2/access_token \
-H 'Authorization: Basic Y2xpZW50X2lkOnNlY3JldA==' \ //dummy auth
--data "code=a14d2c8e-9c8a-4820-8ae1-d9313bb6abe2&grant_type=authorization_code&redirect_uri=YOUR_REDIRECT_URI" //dummy code
I was going to include a pic of their documentation concerning this, but its copyrighted. Basically this is what must be included in the post to the token URL:
The Authorization header is required and must be in the format API_KEY:SECRET_KEY and then url safe base64 encoded.
The body of the request must include the following fields:
code - The authorization code that was sent to your Redirect URI at the end of the OAuth login process (see above).
grant_type - The type of authorization grant in use. In this case code for the authorization code.
redirect_uri - The redirect URI for the application, URL encoded.
Any idea of how to do this in Paw would be greatly appreciated! Right now the only way I can figure it to do each call manually as a request and pass along the pertinent items.
thanks!
Mark
From what I see here, it should be nicely supported by Paw. Here's an example config that should fit your needs:
In Paw, if you do NOT check "Set client credentials in the body", it will set the Client Key and Secret in the Authorization header exactly as you described (base64, separated by a :, that's the Basic Auth format).
Otherwise, things should be working ok. Let me know if you need any help.
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).