First of all let me tell you that the code I am writing is not to be used for any socials or app but for a private REST API.
I was able to get the access token, but now when I am using it I get a 401 error.
The documentation I have been given uses Python and a third party dll called Requests (http://docs.python-requests.org/en/latest ). Both documentation and library are not of any use for me as I am developing in DOT NET.
According to the code example: # This request uses a custom authentication method which adds the access token to the request according to the OAuth2 specification.
so I am using this line:
request.Headers.Add("x-Authorization", "Access_Token access_token=" + Tok);
whereas the python line of code is this
response = requests.get(list_transfers_endpoint, auth=AccessTokenAuth(access_token), verify=False, params=payload)
where list_transfers_endpoint is the URL
payload is just another parameter that I can add it to the request
verify false is used because test servers do not have an approved SSL certificate. I am overcoming to the SSL problem by using this line
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
which worked for getting the token.
Any Ideas?
Related
I'm currently developing an Single Page Application (SPA) that is attempting to implement EPIC's Standalone Launch with Dynamic Registration. I am currently stuck on the step that requires the SPA to register itself at the https://fhir.epic.com/interconnect-fhir-oauth/oauth2/register endpoint with a JSON Web Key Set. Every time I do this, I get a response back:
{
"error": "invalid_client_metadata",
"error_description": null
}
The request I'm sending looks like the following:
POST https://fhir.epic.com/interconnect-fhir-oauth/oauth2/register
Content-type: application/json
Authorization: Bearer <redacted>
{
"software_id":"<sandbox-id>",
"jwks":{
"keys":[
{
"e":"AQAB",
"kty":"RSA",
"n":"tK2-...<redacted>...Q93sc",
"kid":"1"
}
]
}
}
I'm generating private/public key pairs using WebCrypto and I've verified that the JWKS of the public key I'm sending over is valid (I have tested signing and verifying jwt's using WebCrypto and validated them on jwt.io)
I've created a minimal reproduction repo on github that shows this issue. I've also deployed that repo so you can see the issue yourself.
To walk through the steps, I've been able to successfully do the following:
1: Request an Authorization Code
2: Exchange the Authorization Code for an Access Token
I am currently stuck on specifically using the Access Token and registering my SPA via the /oauth2/register endpoint. I know that the Access Token I'm receiving back is valid as I can access other protected FHIR endpoints using it. I've tried making the request both in a browser and in Postman, neither seem to work.
I am starting to wonder if anyone has ever been able to successfully register using the dynamic registration endpoint before? Searching google and stack overflow for this specific issue returns nothing.
Couple of things to try:
In web-crypto.ts, you have the hash in the config set like this: hash: "SHA-384". Per the docs, it seems it should be this instead: hash: { name: "SHA-384" }.
If that doesn't work, try bumping down the key length to 2048.
Also, this isn't causing your issue but fyi that your scope parameter in the /authorize call is invalid. Valid scopes are openid and fhirUser (can include both separated by a space).
I'm trying to set up Pac4j in my back end (BE) application and in order to configure my Angular front end (FE), I need to understand the workflow that it expects in order to configure the back end properly.
I've been reading reams of documentation and trawling through Pac4j source to find how I get the token from the code without exposing the client secret.
So...
I try to log in FE->BE (without auth)
I receive a 401
I take the 'Location' (the Google auth uri) from the 401 and redirect to it, providing a callback uri
I log in to Google
I am redirected back to my callback uri with a code
(What request do I make to BE in order to get a token back? i.e. where is the token URI that doesn't require a client_secret)
I use the retrieved token to access and continue as normal using BE
If you don't want to use client_secret, then you need public client. I'm not sure if public client is supported by Google.
IMHO better approach will be implicit flow in the FE. It will generate access token, which will be used for BE api calls.
I'm creating a Xamarin Forms proof of concept and have hit a bit of a wall with an issue posting to my rest service. The rest service is a Web API 2 Rest service using OAuth Bearer Tokens. I have it running with a valid SSL certificate over https.
I can obtain a token just fine on the device, however, posting with the Bearer token Authorization header causes
System.Net.WebException: cannot parse response.
If I omit the authorization header, the request fails at the server due to authentication. If I include it, the request never goes out to the server (used charles proxy to verify).
The "rest client" is a simple wrapper around HttpClient with ModernHttpClient as a provider, defined in a PCL. The "rest client" works beautiful from a console application. I think I'm seeing an exception from a lower level in iOS related to authentication headers...
This is how I build the HttpClient in the PCL:
Client = new HttpClient(new NativeMessageHandler());
Client.MaxResponseContentBufferSize = 256000;
Client.BaseAddress = new Uri("https://rest-dev.mysub.mydomain.com");
Client.DefaultRequestHeaders.Accept.Clear();
Client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Authentication.AuthorizationToken); // Authentication is where I store the token
Then I post the model with:
var strContent = JsonConvert.SerializeObject(model);
var content = new StringContent(strContent, Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.PostAsync($"api/devices", content);
All of this is covered with a test application which uses the same PCL to post to the server.
Not sure it matters, but in case it does, within the Xamarin Forms PCL this is called within a new Command on login (after the token is obtained).
I have the same error whether I run in iOS simulator or on my device.
I found it interesting that when I don't use ModernHttpClient as a provider, I receive a different error when attempting to obtain a token:
"System.Net.WebException: Error: SendFailure (Error writing headers)"
Research on that lead me down the path of setting up a valid SSL.
Any help in the right direction would be greatly appreciated. My google-fu is at a wall.
Update
I think I'm on to the issue, it's related to the SSL certificate. I used Charles Proxy and had it install its certificate to debug the connections and it just started working. Still does not work without using Charles Proxy, though.
This turned out to be an issue with IIS SSL handshaking. My solution here:
https://serverfault.com/a/779895/42134
I had a similar issue because my webserver is set to only use TLS1.2. The SSL handshake worked after adding:
System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;
to the Startup.Auth.cs -> ConfigureAuth method in the WebAPI as well as in the initialization of the client code.
I have a web api and MVC project,
The web api is deployed at api.domain.com
The MVC app is deployed at domain.com
I recently secured certain methods on the API, it requires authentication (grant type: password).
I want to have the token passed around in the code behind of the MVC app and not javascript, to keep it secure and away from someone sniffing angular js traffic.
I did some research and I should use the HttpClient class. If this is the case how does this client handle refresh tokens? Right now the token expires after 8 hours, I know a refresh token is also issued but does the HttpClient automatically handle this or do I have to write my own logic to check if a request was denied due to an expired token.
Thank you!
I did some research and I should use the HttpClient class. If this is
the case how does this client handle refresh tokens?
The HttpClient class is, as its name suggest, an HTTP protocol client. It knows strictly nothing about OAuth 2.0 and in this respect nothing about refresh tokens. So you should write this logic yourself. Basically the flow you should follow is something along those lines:
Send an HTTP request t othe target endpoint using the HttpClient and including your existing OAuth Bearer token in the Authorization header field.
If the request succeeds then you are good to go. If the request fails with 401, then you should use your refresh token in order to renew your access token and then repeat step 1 with your new access token.
I think using a HttpMessageHandler can help you.
The way this is wired up to an HttpClient is by using the HttpClient constructor that takes a HttpMessagHandler:
1: // Create client and insert an OAuth message handler in the message path that
2: // inserts an OAuth authentication header in the request
3: HttpClient client = new HttpClient(new OAuthMessageHandler(new HttpClientHandler()));
The HttpClientHandler is the default “network” handler provided by HttpClient that actually sends the request and received the response from the network.
Refer this for complete detail: https://blogs.msdn.microsoft.com/henrikn/2012/02/16/extending-httpclient-with-oauth-to-access-twitter/
As part of the OpenID Connect (OAuth2 for Login), my application is supposed to request an access token, given a one-time authorization code, via the endpoint https://www.googleapis.com/oauth2/v3/token. According to documentation, this request needs 5 parameters passed to it, client_id among them. That is exactly what my application does, using the Perl module Net::OAuth2.
Everything has been working fine for several months, but today I was notified that it stopped working. No updates were made to the application code nor the libraries used by it.
The message my application now receives from the server when calling the token endpoint is this, in a 400 error response:
OAuth 2 parameters can only have a single value: client_id
A Google search suggests nobody has ever seen this message before, or lived to tell the tale. There doesn't seem to be a general issue with Google's OpenID Connect (other services based on it are working flawlessly), and the imminent shutdown of the old login protocol doesn't seem relevant.
More testing: removing all parameters except client_id causes this error message:
Required parameter is missing: grant_type
Supplying only client_id and grant_type produces the original error message again.
Does anyone have an idea what's going on here?
Google changed this behavior few days ago, so any OAuth2 library using Basic Auth headers AND body request parameters will start to see messages like
OAuth 2 parameters can only have a single value: client_id
or
OAuth 2 parameters can only have a single value: client_secret
So, you must now do NOT use both (the Auth headers and body request parameters) at the same time to send credentials to Google.
And according RFC 6749, the preferable way to send credentials is through Auth headers (thanks #JanKrüger for alert me about this).
Got the same error. It seems the problem is that NET::OAuth2 sets the authorization header when exchanging authorization code for access token. If you remove this header everything works fine.
Check the get_access_token method in Net::OAuth2::Profile::WebServer module. The authorization header includes client_id:client_secret base64-encoded string. Apparently Google now treats this duplication as an error.
The right way of fixing this is to set the secrets_in_params parameter when creating Net::OAuth2::Profile::WebServer object. Look in the Net::OAuth2::Profile documentation for more details.