How to get id_token from TokenEndpoint of IdentityServer4 through authorization_code flow? - asp.net-core

I would like to get "access_token" and "id_token" from Token endpoint through Authorization Code flow. But, I am getting "invalid_grant" error while calling the token endpoint with following parameters on postman.
POST /connect/token HTTP/1.1
Host: localhost:2000
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache
Postman-Token: a8a29659-0ea3-e7dc-3bd6-6e6630a7370d
client_id=client
&client_secret=client
&grant_type=authorization_code
&username=admin
&password=admin
&scope=openid+profile
Client Configuration:
new Client
{
ClientId = "client",
ClientSecrets =
{
new Secret("client".Sha256())
},
AllowedGrantTypes = new List<string> { OidcConstants.GrantTypes.AuthorizationCode },
AllowedScopes = {
StandardScopes.OpenId.Name,
StandardScopes.Profile.Name,
}
}
What is wrong in my client configuration section? and, How do i make a successful post request to Token Endpoint?

The authorization code grant type requires a code parameter to be sent during the token request (see RFC6749 section 4.1.3).
This code is issued by the authorization server after the resource owner authorized the client (see RFC6749 section 4.1.2).

Related

Authenticate a cognito user using expo AuthSession API

I am using this example code
I am able to get a response from authorize endpoint.
request: {"clientId": "<retracted>", "clientSecret": undefined, "codeChallenge": "t6xISsEiAwOIwQxk0Ty1JNo2Kqa53mECL9a7YahLv_A", "codeChallengeMethod": "S256", "codeVerifier": "<retracted>", "extraParams": {}, "prompt": undefined, "redirectUri": "exp://192.168.0.22:19000", "responseType": "code", "scopes": undefined, "state": "o7FeO9ANoa", "url": "https://<retracted>"//oauth2/authorize?code_challenge=t6xISsEiAwOIwQxk0Ty1JNo2Kqa53mECL9a7YahLv_A&code_challenge_method=S256&redirect_uri=exp%3A%2F%2F192.168.0.22%3A19000&client_id=<retracted>"f&response_type=code&state=o7FeO9ANoa", "usePKCE": true}
LOG response: {"authentication": null, "error": null, "errorCode": null, "params": {"code": "<retracted>"", "state": "o7FeO9ANoa"}, "type": "success", "url": "exp://192.168.0.22:19000?code=<retracted>"&state=o7FeO9ANoa"}
const exchangeFn = async (exchangeTokenReq) => {
try {
const exchangeTokenResponse = await exchangeCodeAsync(
exchangeTokenReq,
discoveryDocument
);
setAuthTokens(exchangeTokenResponse);
} catch (error) {
console.error(error);
}
};
while exchangeFn is being invoked i am getting an error "ERROR [Error: Client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method). The authorization server MAY return an HTTP 401 (Unauthorized) status code to indicate which HTTP authentication schemes are supported. If the client attempted to authenticate via the "Authorization" request header field, the authorization server MUST respond with an HTTP 401 (Unauthorized) status code and include the "WWW-Authenticate" response header field matching the authentication scheme used by the client.]"
Here is the application flow enter image description here
As per Oauth 2.0 while Exchanging an authorization code grant with PKCE for tokens we need to add Authorization header.
The authorization header string is Basic Base64Encode(client_id:client_secret). The following example is an authorization header for app client djc98u3jiedmi283eu928 with client secret abcdef01234567890, using the Base64-encoded version of the string djc98u3jiedmi283eu928:abcdef01234567890
The example code does not include this. That is the issue. we have to get the App client secret from aws cognito and add it to exchangeTokenReq.
const clientId = '<your-client-id-here>';
const userPoolUrl =
'https://<your-user-pool-domain>.auth.<your-region>.amazoncognito.com';
const redirectUri = 'your-redirect-uri';
const clientSecret = 'app-client-secret';
exchangeFn({
clientId,
code: response.params.code,
redirectUri,
clientSecret,
extraParams: {
code_verifier: request.codeVerifier,
},
});

xero api fails with unauthorized (401 or 403) after calling auth, refresh and gettenants when calling getinvoices

I'm a rank noob at this, so excuse my ignorance. I've got an MVC web application to login, get the access and refresh tokens, and tenant list OK. I can even get it to refresh the refresh token. No problems.
When I try to run the GetInvoices endpoint either directly or via the sdk, I get 403 (skd) or 401 from the direct api call.
From the latest run with direct call I get this response
{StatusCode: 401, ReasonPhrase: 'Unauthorized', Version: 1.1, Content:
System.Net.Http.HttpConnectionResponseContent, Headers:
{
Server: nginx
Strict-Transport-Security: max-age=31536000
WWW-Authenticate: OAuth Realm="api.xero.com"
Cache-Control: no-store, no-cache, max-age=0
Pragma: no-cache
Date: Wed, 21 Jul 2021 11:19:56 GMT
Connection: close
X-Client-TLS-ver: tls1.2
Content-Type: text/html; charset=utf-8
Content-Length: 95
Expires: Wed, 21 Jul 2021 11:19:56 GMT
}, Trailing Headers:
{
}}
I know that the access token and tenant id used in the GetInvoices step are correct because I checked them against the values pulled in from the auth steps character by character.
The app is being run in Visual Studio 2019, using the self-signed development SSL certificate.
Why is it rejecting the request?
my controllers have the following
private static readonly string Scopes = "openid offline_access profile email accounting.transactions accounting.contacts accounting.attachments";
private static readonly string Scopes = "openid offline_access profile email accounting.transactions accounting.contacts accounting.attachments";
string[] tenant = (string[])TempData.Peek("tenant");
var client = new HttpClient();
var formContent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("summaryOnly", "true"),
});
client.DefaultRequestHeaders.Add("Authorization", (string)TempData.Peek("accessToken"));
client.DefaultRequestHeaders.Add("Xero-Tenant-Id", tenant[0]);
client.DefaultRequestHeaders.Add("Accept", "application/json");
var response = await client.PostAsync("https://api.xero.com/api.xro/2.0/Invoices", formContent);
The SDK should handle this for you in the helper methods for the client and OAuth flow but i've included what looks like is missing from just a raw API call below.
Core API call - looks like you need to prefix the token with the Bearer string.
Authorization: "Bearer " + access_token
If you are wanting to use the SDK note that there is a sub Nuget package for OAuth helpers that will help you obtain an access token which you need to pass to core api calls.
https://github.com/XeroAPI/Xero-NetStandard/tree/master/Xero.NetStandard.OAuth2Client
(DOH!) The Tenant returns an Id and a TenantId. I was using the Id.
Thanks to SerKnight and droopsnoot for helping.
I've added code from the OAuth2. The help does not mention to get and cast the return type of RequestAcessTokenAsync.
XeroOAuth2Token authToken = (XeroOAuth2Token)await client.RequestAccessTokenAsync(authorisationCode);
also to check the state on return, you must set in xconfig. mine reads
XeroConfiguration xconfig = new()
{
ClientId = Global.XeroClientID,
ClientSecret = Global.XeroClientSecret,
CallbackUri = new Uri(Global.RedirectURI),
Scope = Global.XeroScopes,
State = Global.XeroState
};
var client = new XeroClient(xconfig);
return Redirect(client.BuildLoginUri());

JWT validation with external authority doesn't work. ASP .NET Core 3.0

I am trying to authorize my requests using external service with IdentityServer4. I use following code
services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.Authority = Configuration["IdentityUrl"];
options.RequireHttpsMetadata = false;
options.Audience = "myapi";
});
I got my token using token client
var tokenResponse = await tokenClient.RequestPasswordTokenAsync(
new PasswordTokenRequest
{
ClientId = clientId,
ClientSecret = clientSecret,
GrantType = GrantTypes.Password,
Address = discoveryDocument.TokenEndpoint,
UserName = user.UserName,
Password = user.PasswordHash,
});
It works and gives me token, but then when I try to authorize any request by including this token into authorization header it gives me 401 with no explanation. I don't see anything in output of either idenity server application or my client application.
This is what I do in postman to test authorization
Any ideas on what is wrong and how to debug it?
Try to see what the logs says?
Or try to set this one to true in the AddJwtBearer options and then look at the response from the API to see if it contains some additional details about the failure.
options.IncludeErrorDetails = true;
It it works you should see an additional WWW-authenticate header, like this one:
HTTP/1.1 401 Unauthorized
Date: Sun, 02 Aug 2020 11:19:06 GMT
WWW-Authenticate: Bearer error="invalid_token", error_description="The signature is invalid"

GCP API - OAuth 2.0 from Postman

I have developed an Python webapp on GCP App Engine.
I want to use OAuth 2.0 client ID as an authentication for my app.
In APIs & Services -> Credentials there is an OAuth 2.0 client ID with my app URL added as Authorized redirect URIs.
My Postman access token configuration looks like the following:
And authorization configuration:
Despite that I am getting following response: Status: 401 Unauthorized
Info from the header: WWW-Authenticate: Bearer, error="invalid_token"
Response body:
{
"code": 16,
"message": "JWT validation failed: Bad JWT format: Invalid JSON in header",
"details": [
{
"#type": "type.googleapis.com/google.rpc.DebugInfo",
"stackEntries": [],
"detail": "auth"
}
]
}
What I am doing wrong? How should I troubleshoot this?
EDIT: Adding request
POST /parse HTTP/1.1
Host: [my_app_name].appspot.com
Content-length: 0
Content-type: application/json
Authorization: Bearer [token_generated_by_postman]

Client credential grant type is not properly sent with Apache Oltu client library?

I tried to implement an OAuth client using OAuthClientRequest in Apache Oltu. And it seems to be that it is sending client credentials in the message body not in the Basic Auth headers according to the spec. I am not sure, I may have missed some thing in the code.
Code
OAuthClientRequest.tokenLocation("http://localhost:8081/token")
.setGrantType(GrantType.CLIENT_CREDENTIALS)
.setClientId(clientKey)
.setClientSecret(clientSecret)
.buildBodyMessage();
Request
POST /token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache
Pragma: no-cache
User-Agent: Java/1.6.0_29
Host: 127.0.0.1:8081
Accept: text/html, image/gif, image/jpeg, *; q=.2, /; q=.2
Connection: keep-alive
Content-Length: 127
client_secret=f921854d-f70b-4180-9fdd-3a55032103cc&grant_type=client_credentials&client_id=3f3b4092-7576-4b26-8135-980db7864c2
You might want to change buildBodyMessage() with buildQueryMessage()
The OAuth2 Bearer Token specification defines three methods of sending bearer access tokens:
Authorization Request Header Field
Form-Encoded Body Parameter
URI Query Parameter
The method buildBodyMessage() will create a request with a Form-Encoded Body Parameter. You need to use buildHeaderMessage() instead, which is also the recommended method by the specification.
Recently, I've trying to find a OAuth2 java library to get "client_credential" type of accesstoken. And below is what I have for Apache Oltu, and it seems that it is working.
#Test
public void getAccessTokenViaApacheOltuOAuthClient() {
try{
OAuthClient client = new OAuthClient(new URLConnectionClient());
OAuthClientRequest request =
OAuthClientRequest.tokenLocation(TOKEN_REQUEST_URL)
.setGrantType(GrantType.CLIENT_CREDENTIALS)
.setClientId(CLIENT_ID)
.setClientSecret(CLIENT_SECRET)
.setScope(StringUtils.join(TEST_SCOPES, " ")) //if you have scope
.buildBodyMessage();
String token =
client.accessToken(request, "POST", OAuthJSONAccessTokenResponse.class)
.getAccessToken();
System.out.println(token);
assertTrue( token != null);
} catch (Exception e) {
e.printStackTrace();
}
}