How can I encrypt JWT Token in Web Api C#? - c#

My Jwt Token looks like below:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9leGFtcGxlLm9yZyIsImF1ZCI6Imh0dHA6XC9cL2V4YW1wbGUuY29tIiwiaWF0IjoxMzU2OTk5NTI0LCJuYmYiOjEzNTcwMDAwMDAsImV4cCI6MTQwNzAxOTYyOSwianRpIjoiaWQxMjM0NTYiLCJ0eXAiOiJodHRwczpcL1wvZXhhbXBsZS5jb21cL3JlZ2lzdGVyIiwidGVzdC10eXBlIjoiZm9vIn0.UGLFIRACaHpGGIDEEv-4IIdLfCGXT62X1vYx7keNMyc
If I Copy the above JWT token and paste it in https://jwt.io/ then the actual information is showing like this
Image
I want to encrypt the JWT token with no one can access my information in Web Api. So, I want to use any encryption algorithm, If so please provide me proper solution
Here is my Startup.cs file to authorize JWT Token.
// Api controllers with an [Authorize] attribute will be validated with JWT
app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
AllowedAudiences = new[] { audience },
IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
{
new SymmetricKeyIssuerSecurityTokenProvider(issuer, secret)
}
});
}

Why exactly do you think that it is a problem that someone can see this information? If you are using JWT for authentication, then it's only the user who was just authenticated will get this token and it probably contains the information about this user. So it does not hurt for a user to be able to see information about himself.
Most importantly the token is mac'ed so that no one can forge it and pretend to be another user and that should be sufficient.
And as mentioned in the comments you should be using TLS anyway, so it's encrypted in the transition.

Related

How does API Gateway validates the JWT token?

The documentation states: API Gateway validates the token on behalf of your API, so you don't have to add any code in your API to process the authentication.
My question is how?
To authenticate a user, a client application must send a JSON Web Token (JWT) in the authorization header of the HTTP request to the backend API.
So for API Gateway to authenticate the user it needs to know the secret key to calculate signature of a header and payload of JWT to compare it with the signature from JWT.
How does it do that?
My code to verify token is like below and I imagine the API gateway would be using something similar to that - so the _appSettings.Secret is needed:
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
tokenHandler.ValidateToken(token, new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false,
// set clockskew to zero so tokens expire exactly at token expiration time (instead of 5 minutes later)
ClockSkew = TimeSpan.Zero
}, out SecurityToken validatedToken);
Assuming you're talking about AWS API Gateway; It does require the secret key used for signing the original JWT token but mostly for custom authorization schemes as the documentation states.
A Lambda authorizer is useful if you want to implement a custom authorization scheme that uses a bearer token authentication strategy such as OAuth or SAML, or that uses request parameters to determine the caller's identity.
To achieve this the API Gateway takes a Lambda authorizer to use in the authorization process. You provide the Lambda authorizer with the required details such as the secret key used to sign your JWT token and it can then verify the token based on that. See this AWS example for more details on the implementation.
The API Gateway will then use the provided detail to verify your JWT tokens and authorize a request.

Web API Validate JWT Bearer Token from Custom Auth Provider

I've been looking for an example or tutorial for a few hours and thought I should post something at this point.
I'm trying to validate a bearer token from a custom Auth provider inside my .Net 4.7.2 Web Api 2 project. I have a SPA app that gets a bearer token from this auth provider, and sends the bearer token to my WebApi endpoints. I need to turn around and validate the token in each request. I thought there would be a way to point the classes in the Microsoft.Owin.Security.Jwt namespace to validate the token based on the auth providers well known discovery information url.
Has anyone done this before or point me towards a good library/documentation/tutorial?
I know I can write my own auth request filter and go out and pull down the public certificate from the auth server and parse the token and validate the signature, but it seems like a horrible idea for me to write that myself vs using the appropriate libraries.
Ok turns out I found a good example here
The following code sets up our webapi to validate tokens with our custom auth provider while discovering the public key through the OIDC discovery url.
var issuer = "https://my-auth-provider-here/";
IConfigurationManager<OpenIdConnectConfiguration> configurationManager =
new ConfigurationManager<OpenIdConnectConfiguration>($"{issuer}.well-known/openid-configuration", new OpenIdConnectConfigurationRetriever());
OpenIdConnectConfiguration openIdConfig = configurationManager.GetConfigurationAsync(CancellationToken.None).Result;
appBuilder.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions()
{
AuthenticationMode = AuthenticationMode.Active,
TokenValidationParameters = new TokenValidationParameters()
{
AuthenticationType = "Bearer",
ValidIssuer = issuer,
ValidateAudience = false,
IssuerSigningKeys = openIdConfig.SigningKeys
}
});

Web Api OWIN - How to validate token on each request

I have two applications
Client application build on ASP.NET MVC
Authentication server build on Web API + OWIN
Have planned authentication as follow
For user login client app will make a request to authication server with logged in credential.
Authication server will generate a token and will send back to client application.
Client application will store that token in local storage.
for each subsequent request client app will attached token kept in local storage in request header.
NOW, ON SERVER SIDE OF CLEINT APP I NEED TO VALIDATE THAT TOKEN COMES WITH EACH REQUEST IS NOT TEMPERED.
Please suggest me how to validate token in each request as i don't know the key the OWIN has used to generate the token.
Is is right to write code to validate token on client app or it should be on authication server.
I am planning to shift all user management code like register user, change password to authentication server so than we can re-use it for different client app- is it right design practice?
So far i have wrote below code to just to create a POC.
=========================OWIN configuration========
[assembly: OwinStartup(typeof(WebApi.App_Start.Startup))]
namespace WebApi.App_Start
{
public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
ConfigureOAuth(app);
WebApiConfig.Register(config);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(config);
}
public void ConfigureOAuth(IAppBuilder app)
{
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = false,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new SimpleAuthorizationServerProvider(),
};
// Token Generation
app.UseOAuthAuthorizationServer(OAuthServerOptions);
app.UseOAuthBearerAuthentication(new
OAuthBearerAuthenticationOptions());
}
}
}
==============================oAuth Provided========================
public class SimpleAuthorizationServerProvider: OAuthAuthorizationServerProvider
{
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
context.Validated();
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
using (AuthRepository _repo = new AuthRepository())
{
IdentityUser user = _repo.FindUser(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
}
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
identity.AddClaim(new Claim("sub", context.UserName));
identity.AddClaim(new Claim("role", "user"));
context.Validated(identity);
}
}
Please help,
Thanks,
#Paul
Please suggest me how to validate token in each request as i don't
know the key the OWIN has used to generate the token.
Your current setup, were you have added the app.UseOAuthBearerAuthentication() to the owin pipeline, will authenticate the user from the bearer token which is passed on each request for you.
The current user can then be found via HttpContext.Current.User.
Use the Authorize attribute to then decide which users are authorized on certain endpoints.
Here's an example where users with the role "user" are allowed to access
[Authorize(Roles="user")]
public class ValuesController : ApiController
{
}
Is is right to write code to validate token on client app or it should
be on authication server.
NO, you don't validate the token in client, if your user credentials are wrong you wont get a token at all. That's all you need to know.
And also, why should you want to validate the token in the client?
I am planning to shift all user management code like register user,
change password to authentication server so than we can re-use it for
different client app- is it right design practice?
Reusing a token provider is common. Why invent the wheel for every application? Build one great, or use a third party, and reuse it across your applications.
Use JSON Web Tokens (JWT) and claims identities, not random tokens that require keeping track of the issued tokens.
A JWT is like a passport issued by a trusted authority. The passport is signed/stamped, and you can verify that it was issued by this trusted authority and that it has not been tampered with. That means, the integrity of the access-right claim present in the token can be verified without keeping state anywhere. The only communication that needs to happen between the trusting application and the authority is an initial (secure) download of the authority's public key (used for signing the tokens).
It's also advisable that you use a standard claims schema, like OpenID Connect ( http://openid.net/specs/openid-connect-core-1_0.html#StandardClaims )
A good book on the topic, which helped me a lot getting an understanding of all these concepts, can be found here: A Guide to Claims-Based Identity and Access Control.
One way to verify a token has not been tampered is to sign it using an asymmetric key pair, Identity Server uses this approach as seen here.
In your case if you are rolling your own authentication you will need to implement this yourself, and check on every request probably in a custom middleware that the token is valid.
If you create, sendback, save in localStorage and every thing about JWT Token as correct, you have to know that many ways are in .Net that you can to controlling per request.
Server side controlling:
If you are using Web API Core, in core you can create Middleware that runs as pipline in run time, and you can give context and check token that requested, for more infomation check: This.
If you use of Asp.net MVC, you can use ActionFilter in MVC(Asp.Net-Core have more advance ActionFilter too), that each requests goes through on and you can check every thisng abount request, for more information check: This.
ClientSide Conftolling:
After that you give Token after log in from server side, you have to save data in localstorage that your browser check per request that data, they advantage are the Expireation and every like this issue in token save in localstorage and you and browser can use of this for more information check: This.
GoodLuck.

Validating an access token in my ASP.NET Web API

I have a mobile client (app) letting the user authenticate with google. So, the client receives an access token and some info (name, email etc) from google. Works fine!
I also created an ASP.NET Web API that the mobile app should comunicate with. On the client side I am adding the token to the HttpClient with:
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "pretty_long_access_token_separated_by_two_dots");
Question 1: I'm trying to "decode" the access token on this site (to make sure it's all right): https://jwt.io/
The header and the payload is all right, but it seems like it's an "invalid signature" (says in the bottom). Should I worry about this?
On the server side, I added this to the Configuration method in the Startup class:
app.UseJwtBearerAuthentication( new JwtBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
AllowedAudiences = new List<string> {"my_client_id"},
IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
{
new SymmetricKeyIssuerSecurityTokenProvider(#"https://accounts.google.com/", "my_client_secret")
},
});
The only thing I want to do with the token, on my server side, is making sure that only validated users from my app should be able to access my API-controller.
Question 2: Is UseJwtBearerAuthentication the right thing for me, or am I going in the wrong direction?
My problem is, I constantly get 401, unauthorized, when trying to access my WEB API controller.
If I am on the right track, I can try to explain more about the server side setup...
Any helt would be very appreciated!
If you are using a JWT token then you will need JWT instead of Bearer
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("JWT", "pretty_long_access_token_separated_by_two_dots");
The signature is used to validate the token as authentic and is therefore only required by the authentication server. If Google is your authentication server, then there should be an API endpoint you can call from your server to verify that the token is valid.
If your server is issuing the JWT token, then you will need to check that the token is valid by decoding the signature using the secret that was used to create it in the first place
If Google is issuing the JWT and you want your server to be able to self validate it, then you need to use another encryption type such as RS256 which will allow you to validate the signature using a public key issued by Google (I have no idea if they provide this method or not)
The reason https://jwt.io/ cannot validate your signature is because it was signed using a secret code. If you have this secret code then you are able to paste it into the textbox in the bottom right. If the secret is correct, and the token hasn't expired, it will show as being a valid JWT token.

Ws-Federation Identity Information Not Available in Web API?

I'm using Ws-Fed Authentication OWIN middleware to authenticate an ASP.NET MVC app with Web API endpoints using ADFS. I'm able to sign in using ADFS successfully, and on my MVC controllers, HttpContext.User.Identity.IsAuthenticated is true - I can see the claims information for the signed in user as well.
However for WebAPI endpoints, User.Identity.IsAuthenticated is false. The claims information for the signed is user is also unavailable. Is there any way that I expose the fact that the user is authenticated for both MVC and WebAPI controllers?
Here is how I am configuring my authentication middleware in the OWIN Startup class:
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
ExpireTimeSpan = TimeSpan.FromMinutes(sessionDuration),
SlidingExpiration = true //expiration extended after each request
});
app.UseWsFederationAuthentication(
new WsFederationAuthenticationOptions
{
Wtrealm = realm,
MetadataAddress = metadata,
Notifications = new WsFederationAuthenticationNotifications
{
AuthenticationFailed = context =>
{
context.HandleResponse();
context.Response.Redirect("/?loginfailed=loginfailed");
return Task.FromResult(0);
}
}
});
Try adding a "Name Id" claim to ADFS:
http://darb.io/blog/2014/06/30/WebAPI-and-ADFS-as-external-login-provider/
So I discovered the answer to this question by examining the OWIN cookie authentication middleware source code on CodePlex. Cookies created using the middleware by an MVC controller are created differently from cookies created Web API. MVC cookies are a reference to user information stored in session, and since Web API is completely stateless (no session), cookies created in MVC can not be used in Web API.
In addition, it is bad practice to use cookie authentication in Web API anyways; bearer token authentication is a preferable option.
In my case where I needed to use Ws-Federation authentication, the solution was to:
Add bearer token authentication middleware to my app
Create a Web API endpoint (ideally cryptically named) that will securely receive Ws-Federation claims, perform validation to ensure the request really came from your MVC controller, use them to generate a bearer token, and respond with the generated bearer token
Upon authenticating in MVC, serialize the claims, and marshal them over to Web API using the endpoint created earlier
Add the bearer token to a hidden field in the SPA
Many, many thanks to #Juan for providing me with feedback and links to point me in the right direction.

Categories