Validating token in client application - validation

I have an application which accepts JWTtoken and go through the claims and respond to the request. Once I receive the JWTtoken, I want to validate whether it is issued by the Identity server which I trust.
Any idea how an application can perform JWTtoken validation?
an application simply make call:
/connect/identitytokenvalidation?token=&client_id= and get the token validation done?
Do I need to create TokenClient instance to call RequestAssertionAsync? or I can simply make http get request by passing token value in the query string?
I can get the token value with the following way:
Request.GetOwinContext().Request.Headers["Authorization"];
Any sample would be of a great help.

If your endpoint is running in a Katana pipeline then you can use either the Microsoft JWT bearer authentication middleware, or you can use the IdentityServer3.AccessTokenValidation middleware. Either of these will be the proper validation.
If you don't want to use those and do it manually, then you can use the Microsoft JwtSecurityTokenHandler class to perform the validation.
Here's the relevant lines of code from our sample web api
https://github.com/IdentityServer/IdentityServer3.Samples/blob/master/source/Clients/SampleAspNetWebApi/Startup.cs
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
Authority = "https://localhost:44333/core",
RequiredScopes = new[] { "write" },
});

Related

How to access JWT in Quarkus when proactive auth is disabled?

I need to access a jwt sent in authorization header. I also have to disable the proactive auth check. How can I get the token?
I have this class which used to work when proactive auth was enabled:
#RequestScoped
public class AccessRights {
#Inject
JsonWebToken accessToken;
public boolean validateAccess() {
if(accessToken.getRawToken() == null)
throw new AccessDeniedException("Invalid Access Token");
JsonObject claim = accessToken.getClaim("claim");
// ... do some validation ...
}
}
When I set quarkus.http.auth.proactive=false it stops working. The accessToken is always null. Now that is expected since its documented here https://quarkus.io/guides/security-jwt#proactive-authentication and here https://quarkus.io/guides/security-built-in-authentication#proactive-authentication. I tried to use the alternative way suggested in the docs, but I cannot get it to run.
Problem: I don't know how to get a JsonWebToken from the suggested workaround
Problem: Even when I try to use securityIdentity instead, it is always null. Plus I don't know yet how to actually use it for validation.
#RequestScoped
public class AccessRights {
#Inject
CurrentIdentityAssociation currentIdentityAssociation;
public boolean validateAccess() {
SecurityIdentity identity = identities.getDeferredIdentity().await().indefinitely();
// identity is always null
}
}
EDIT:
To add more context: I have a graphQL API and the initial problem was, that if I receive an expired token, the framework will respond with a 401 unauthorized error. However as is best practice in graphQL, I need to respond with a 200 with json body that describes the error. The proactive auth check prevents the graphql error handler to kick in. That is why I disabled it, effectively making things worse.
Here is how the whole auth process in my application works:
The API receives a request that should contain a bearer token (JWT) in the authorization header. The token is acquired somewhere else. My application needs to validate the issuer and expiration time. This part used to be handled by the pro-active auth check. After that my custom validateAccess() method will extract some roles from the token. If those roles are not present, I will call an external api, providing the raw token, to get back some more detailed access rights.
I believe you missed something important here.
Docs says that :
By default, Quarkus does what we call proactive authentication. This means that if an incoming request has a credential then that request will always be authenticated (even if the target page does not require authentication).
Which implicitly means : if you disable proactive auth, you need to require auth to be done before accessing resource.
That may be part of your problem, as you disabled proactive auth, you'll have to explicitly restrict access to resources to authenticated clients. Otherwise, no auth is performed and thus SecurityIdentity is null.
If you already tried that, please add more code and context. I'll gladly edit my response.
EDIT 1 :
I see 2 distinct problems in informations you added :
You got to validate token (if proactive auth is disabled)
You got to get response code 200 with error details instead of 401
But as you clearly stated, token validation works out of the box with proactive enabled.
So, I would suggest you to let proactive auth do its job. Then, I would add an ExceptionMapper.
This way, you can write custom code for Exception unfolding, and you can respond what you want for every situation.
See ExceptionMappers documentation for more

AWS Cognito: Add custom claim/attribute to JWT access token

My app creates a custom attribute "userType" for each new signed-up user. Now I would like this "userType" claim/attribute to be added to the JWT access token whenever the user signs in or the token gets refreshed.
Is there an option to tell cognito to add my custom claim/attribute to the JWT access token? (Without a pre token generation Lambda)
Custom attributes are not available in Cognito access token. Currently it is not possible to inject additional claims in Access Token using Pre Token Generation Lambda Trigger as well. PreToken Generation Lambda Trigger allows you to customize identity token(Id Token) claims only.
You can use ID token to get the token with custom attributes.
Access tokens are not intended to carry information about the user. They simply allow access to certain defined server resources.
You can pass an ID Token around different components of your client, and these components can use the ID Token to confirm that the user is authenticated and also to retrieve information about them.
How to retrieve Id token using amazon cognito identity js
cognitoUser.authenticateUser(authenticationDetails,{
onSuccess: function(result) {
var accessToken = result.getIdToken().getJwtToken();
console.log('accessToken is: ' + accessToken);
},
onFailure: function(err) {
alert(err.message || JSON.stringify(err));
},
});
I have the same problem when I want to create several microservice. There isn't a way I can customize an access token, but only an identity token. However, I use client credentials in the machine-to-machine which needs access token. So, in no way I can customize my token. At last, I decide to add such info(like user type) in the event header. It's not a very secure way compared to customize a token, but there isn't any other easy way to do it right now. Otherwise, I have to rewrite the authorizer in Cognito. Like rewriting a customize authorizer and it's very painful.
I have the same issue with Cognito; exist other tools like "PingFederate"Auth-server of Ping identity and Auth0 Auth-server; I know that the requirement isn't part of the standard, but these applications were my alternatives to fix this issue
The responses suggesting to use the ID Token for authorization in your backend systems are bad security practice. ID Tokens are for determining that the user is in fact logged in and the identity of that user. This is something that should be performed in your frontend. Access Tokens on the other hand are for determining that a request (to your backend) is authorized. ID Tokens do not have the same security controls against spoofing that Access Tokens have (see this blog from Auth0: https://auth0.com/blog/id-token-access-token-what-is-the-difference/).
Instead, I recommend that your backend accept an Access Token as a Bearer token via the Authorization HTTP header. Your backend then calls the corresponding /userinfo endpoint (see: https://openid.net/specs/openid-connect-core-1_0.html#UserInfo) on the authorization server that issued the Access Token, passing such said Access Token to that endpoint. This endpoint will return all of the ID Token information and claims, which you can then use to make authorization decisions in your code.

chatbot: how to validate incoming requests from google hangouts

We've put together a google hangouts chat bot to provide some convenient functionality for our team. The bot is of the 'bot URL' variety, meaning that hangouts sends requests to an app endpoint and our app responds appropriately. At the moment, we're struggling to now validate the incoming requests from google. Each request has a bearer token in the Authentication header, but that JWT token does not validate. Both the php client library [https://github.com/googleapis/google-api-php-client] and the online validator [https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=] return the error 'invalid signature'
The google client php library's Google_AccessToken_Verify class has a verifyIdToken method which we use as described here in this example [https://github.com/GoogleCloudPlatform/php-docs-samples/blob/master/auth/src/auth_cloud_explicit.php]. We pass the path of our service account key file and the project ID into the google client constructor. Then we pass the incoming request's bearer token into the verifyIdToken method.
use Google_Client;
// inside a laravel controller with $request in scope
$bearer_token = $request->bearerToken();
$keyPath = FILE_LOCATION
$client = new Google_Client([
'keyFilePath' => $keyPath,
'projectId' => GCP_CLIENT_ID
]);
$payload = $client->verifyIdToken($bearer_token);
if(!empty($payload)){
return $this->call(ParseGoogleChatRequest::class, [$request]);
}else{
\Log::debug('bad token');
}
I expect the google client library to be able to validate a google JWT. This github issue [https://github.com/firebase/php-jwt/issues/175] reflects our experience implementing this approach. I would like to get some general guidance on which approach we should be using.
I figured out an acceptable solution with the help of another SO question. The google client library was already importing firebase/php-jwt, so I followed along the same lines as Jed from the question I linked to. Extracting the KID from the token, I used it to identify the correct public key from this url. Then I instantiated the php-jwt library and called the decode method on it, passing the required arguments. The decode method also verifies the signature and returns the components of the JWT on success.

Bot DirectLine Token Distribute Issue

based on this Bot DirectLine Authentication,
If you plan to distribute the token to clients and want them to initiate the conversation, use the Generate Token operation.
Does this mean we can generate token from backend using Secret and distribute the token to the client for starting a conversation?
To test it, I wrote these:
Backend: #Azure Function
[FunctionName("XXXXX")]
public static async Task<object> RunAsync([HttpTrigger(Route = "XXXXX")] HttpRequestMessage req, TraceWriter log)
{
log.Info($"Webhook was triggered!");
var tokenResponse = await new DirectLineClient(directLineSecret).Tokens.GenerateTokenForNewConversationAsync();
return req.CreateResponse(HttpStatusCode.OK, tokenResponse.Token);
}
and
Client #UWP
// token from Backend
directLineClient = new DirectLineClient(token);
var conversation = directLineClient.Conversations.StartConversation();
weird thing is the variable conversation is null.
When I put the Generate Token code of Backend to Client, it works that the variable conversation is a valid object.
my question is: can we put the Generate Token in backend and distribute token to clients?
my question is: can we put the Generate Token in backend and distribute token to clients?
Of course, if you do not want to expose/share Direct line secret publicly, you can generate Token in backend service and distribute the token to clients and let them to initiate the conversation.
Note: please make sure the Direct Line token generated by your http triggered function is not expired when you use it in your DirectLine Client.
I do a test with DirectLineClient of Direct Line Bot Sample, and modify the code to accept the Direct Line token. If I provide a Direct Line token that is expired, starting conversation will fail.
The problem is that the backend should return token as text media type. much appreciated for your feedback and reminding.
return req.CreateResponse(HttpStatusCode.OK, tokenResponse.Token, "text/plain");

Identityserver3: Token validation requests not visible in Fiddler

In fiddler composer, I execute a call to a local api that is secured by a local identityserver3.
I added the token, and I configured the middleware to validate the token on the server. Tt works fine, in Idenityserver3 log file I see a succesful token validation logmessage for the configured scope.
I assume that, with htis config, each time the api is called, the Idsrv3 middleware calls the token validation endpoint under the hood.
My issue is that fiddler does not show this middleware request, just the call to the api itself. Is this due to fiddler settings or is there another reason this request is invisible to fiddler?
Is there a way to display it?
Thanks
It could be that .NET is not routing the localhost traffic to fiddler proxy. For workaround check this.
http://docs.telerik.com/fiddler/observe-traffic/troubleshooting/notraffictolocalhost
Also, check if you have configured validation mode properly. According to documentation https://identityserver.github.io/Documentation/docsv2/endpoints/identityTokenValidation.html validation endpoint is useful if you have no access to crypto libraries locally.
Valid validation modes are
ValidationMode.Both - Use local validation for JWTs and the validation endpoint for reference tokens
ValidationMode.Local - Use local validation oly (only suitable for JWT tokens)
ValidationMode.ValidationEndpoint - Use the validation endpoint only (works for both JWT and reference tokens)
You can set the validation mode in IdentityServerAuthenticationOptions
app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
{
Authority = "https://localhost:44333/core",
//RequiredScopes = new[] { "write" },
// client credentials for the introspection endpoint
ClientId = "write",
ClientSecret = "secret",
ValidationMode = ValidationMode.Local
});

Resources