Updated to use latest : System.IdentityModel.Tokens.Jwt 6.8.0
Jwt Web Api c# Development Environment:
- Visual Studio 2019
- .NET Framework 4.7.2
- PostMan or we can use free tool Talent API Tester Chrome plugin https://chrome.google.com/webstore/detail/talend-api-tester-free-ed/aejoelaoggembcahagimdiliamlcdmfm?hl=en
- Nugget Packages used
- System.IdentityModel.Tokens.Jwt -Version 6.8.0 -It will help in validating, parsing and generating JWT tokens; there are other libraries that do this task you are free to choose any package that handle JWT tokens.
for ASP.NET Core 6 based implementation here is the link.
ASP.NET CORE 6 JWT Authentication
Let’s ask our self some Prerequisite question before start working on JWT Implementation
Prerequisite Knowledge
Do you know what is a HttpMessageHandler & DelegatingHandler in ASP.NET ? If not then I would highly recommended reading this post . httpmessagehandler c# example
Do you know basics of jwt web api JWT(Json Web Token)? If not then Visit jwt.io for learning more about JWT . Chris has also provided good details about JWT info.
Implementation :
Let’s move on to actual work that need to be done. Two basic mechanism for securing WEB API
- Using Traditional Cookie based authentication
- Using Token Based Authentication – In simple words our goal is to secure data transmission between two endpoints JWT is a way to achieve.
- Json Web Token Consist of Three parts
- Header
- Claim
- Signature
- Json Web Token Consist of Three parts
Both jwt authentication methods and Cookie based have pros and cons and that is out of the scope of this article and either of the methods should be adopted based on circumstances. we will follow Token Based Authentication Using jwt authentication. The mechanism is not complex once we get understanding of workflow. So the key is not to jump on code right away but understand flow of request. Let’s do it
- User Enter username and password on mobile/web application and press login.
- User Credentials are sent to WEB API endpoint.
- We Intercept HTTP Request and check if the header has JWT token(it will not be there for the first request) if not then we verify username and password and if credentials are correct, we create a JWT token using the library and send it is back in the response body.Next time client request protected resource with this token in a header so for the subsequent request we intercept HTTP request and validate token.
Image below shows flow of information between your browser/mobile and server.
Let’s start coding for our JWT WEB API C#
1- Create a New Project and Name your Project and Solution and Select ASP.NET application. In Latest Visual studio there are couple of steps to do it.
Give your project a name and Click Create
Select Web API as project type and click Create.
The default project layout is listed below for reference.
if you prefer reading then continue below with the article. Video Version of this article below make sure you subscribe.
4. Now Let’s install this Nuget Pacakge. System.IdentityModel.Tokens.Jwt -Version 6.8.0
This is done using package manager console. You can access it under Tools dropdown in NuGet Package Manager as directed the next listing .
Run the command below in the console. screenshot reference below. Install-Package System.IdentityModel.Tokens.Jwt -Version 6.8.0
We need two model classes or in old school term POCO classes to encapsulate response and request. you can add them where seem appropriate.
public class LoginRequest
{
public string Username { get; set; }
public string Password { get; set; }
}
you will need following two import for LoginResponse Classs
using System.Net.Http;
using System.Web.Http;
public class LoginResponse
{
public LoginResponse()
{
this.Token = "";
this.responseMsg = new HttpResponseMessage() { StatusCode = System.Net.HttpStatusCode.Unauthorized };
}
public string Token { get; set; }
public HttpResponseMessage responseMsg { get; set; }
}
Verifying The jwt web api c# :
5. we will need to add a class at root level that extends from DelegatingHandler and we will override SendAsync method. Please note the purpose of adding this class is to intercept incoming HTTP Request and Retrieve and Validate Token.
Until this point if you don’t know what is purpose of DelegatingHandler is Please read this post before moving forward. HTTP Message Handler in Web API
Let’s name this class TokenValidationHandler see code snippet below and follow it carefully. click on Add to add a new class.
Don’t just copy paste every thing listed below along with namespace as your name can be different if you still want to copy make sure you use your namespace . Make note of main package used in first line using microsoft identitymodel tokens
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
namespace WebAPIWT
{
internal class TokenValidationHandler : DelegatingHandler
{
private static bool TryRetrieveToken(HttpRequestMessage request, out string token)
{
token = null;
IEnumerable<string> authzHeaders;
if (!request.Headers.TryGetValues("Authorization", out authzHeaders) || authzHeaders.Count() > 1)
{
return false;
}
var bearerToken = authzHeaders.ElementAt(0);
token = bearerToken.StartsWith("Bearer ") ? bearerToken.Substring(7) : bearerToken;
return true;
}
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
HttpStatusCode statusCode;
string token;
//determine whether a jwt exists or not
if (!TryRetrieveToken(request, out token))
{
statusCode = HttpStatusCode.Unauthorized;
//allow requests with no token - whether a action method needs an authentication can be set with the claimsauthorization attribute
return base.SendAsync(request, cancellationToken);
}
try
{
const string sec = "401b09eab3c013d4ca54922bb802bec8fd5318192b0a75f201d8b3727429090fb337591abd3e44453b954555b7a0812e1081c39b740293f765eae731f5a65ed1";
var now = DateTime.UtcNow;
var securityKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(System.Text.Encoding.Default.GetBytes(sec));
SecurityToken securityToken;
JwtSecurityTokenHandler handler = new JwtSecurityTokenHandler();
TokenValidationParameters validationParameters = new TokenValidationParameters()
{
ValidAudience = "http://localhost:50191",
ValidIssuer = "http://localhost:50191",
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
LifetimeValidator = this.LifetimeValidator,
IssuerSigningKey = securityKey
};
//extract and assign the user of the jwt
Thread.CurrentPrincipal = handler.ValidateToken(token, validationParameters, out securityToken);
HttpContext.Current.User = handler.ValidateToken(token, validationParameters, out securityToken);
return base.SendAsync(request, cancellationToken);
}
catch (SecurityTokenValidationException e)
{
statusCode = HttpStatusCode.Unauthorized;
}
catch (Exception ex)
{
statusCode = HttpStatusCode.InternalServerError;
}
//@josbol mentioned this issue in 2018
//Since this solution pushes the request further down the pipeline, instead of immediately returning, this
//solution consumes more resources for each request, so this might not be the right solution for everybody.
//Alternatively one could manually add the missing headers before returning,
//but I don't think that would be a good idea.
//- this line would return correct CORS header.- credit to
//return base.SendAsync(request, cancellationToken);
return Task<HttpResponseMessage>.Factory.StartNew(() => new HttpResponseMessage(statusCode) { });
}
public bool LifetimeValidator(DateTime? notBefore, DateTime? expires, SecurityToken securityToken, TokenValidationParameters validationParameters)
{
if (expires != null)
{
if (DateTime.UtcNow < expires) return true;
}
return false;
}
}
}
we wrote a custom Message Handler, we defined our own class that derived from the DelegatingHandler class and we override SendAysnc method.
This code will intercept HTTP request and validate the JWT.
Generating the JWT Token Web Api C#:
6. Next thing is we need to create a JWT after verifying the username and password with our database. For this purpose, I am going to create a controller. Let’s name it LoginController.cs
- Don’t just copy paste every thing listed below along with namespace as your name can be different if you still want to copy make sure you copy controller and required imports.
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Security.Claims;
using System.Web;
using System.Web.Http;
namespace WebAPIWT.Controllers
{
public class LoginController : ApiController
{
[HttpPost]
public IHttpActionResult Authenticate([FromBody] LoginRequest login)
{
var loginResponse = new LoginResponse { };
LoginRequest loginrequest = new LoginRequest { };
loginrequest.Username = login.Username.ToLower();
loginrequest.Password = login.Password;
IHttpActionResult response;
//HttpResponseMessage responseMsg = new HttpResponseMessage();
bool isUsernamePasswordValid = false;
if (login != null)
isUsernamePasswordValid = loginrequest.Password == "admin" ? true : false;
// if credentials are valid
if (isUsernamePasswordValid)
{
string token = createToken(loginrequest.Username);
//return the token
return Ok<string>(token);
}
else
{
// if credentials are not valid send unauthorized status code in response
loginResponse.responseMsg.StatusCode = HttpStatusCode.Unauthorized;
response = ResponseMessage(loginResponse.responseMsg);
return response;
}
}
private string createToken(string username)
{
//Set issued at date
DateTime issuedAt = DateTime.UtcNow;
//set the time when it expires
DateTime expires = DateTime.UtcNow.AddMinutes(10);
//http://stackoverflow.com/questions/18223868/how-to-encrypt-jwt-security-token
var tokenHandler = new JwtSecurityTokenHandler();
//create a identity and add claims to the user which we want to log in
ClaimsIdentity claimsIdentity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, username)
});
const string sec = "401b09eab3c013d4ca54922bb802bec8fd5318192b0a75f201d8b3727429090fb337591abd3e44453b954555b7a0812e1081c39b740293f765eae731f5a65ed1";
var now = DateTime.UtcNow;
var securityKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(System.Text.Encoding.Default.GetBytes(sec));
var signingCredentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(securityKey, Microsoft.IdentityModel.Tokens.SecurityAlgorithms.HmacSha256Signature);
//create the jwt
var token =
(JwtSecurityToken)
tokenHandler.CreateJwtSecurityToken(issuer: "http://localhost:50191", audience: "http://localhost:50191",
subject: claimsIdentity, notBefore: issuedAt, expires: expires, signingCredentials: signingCredentials);
var tokenString = tokenHandler.WriteToken(token);
return tokenString;
}
}
}
we have CreateToken method that generates a token and Authenticate method receive an HTTP request and we validate the username and password and if they are valid we send back the Token.
7. Next step is where we will register Message Handler class. Add following lines in WebApiConfig.cs
config.MessageHandlers.Add(new TokenValidationHandler ());
8 . Securing our controller ; Let’s decorate our Values Controller with Authorize attribute and Run the project press F5
9 . jwt web api c# Testing
you can use any Rest client tool to make a post call to these endpoints like Postman, fiddler or chrome extension . we will use Talend API Tester – Free Edition.
so here is the work flow
1- Obtaining JWT token for webapi c# : Make a POST call to Authenticate endpoint by providing username/password to get the token.
2- Using the Token to access secure endpoint of jwt web api C#: we will use token to get access to secure resource in our case any endpoint in values controller.
As you can see I added the token in the header do notice syntax Bearer token . we accessed our secured resource using JWT. It is valid for about of time we set when we generated it . if we temper with it unauthorized code is returned.
Code for JWT Web Api:
https://github.com/seanonline/Webapi_JWT_Authentication
Step by Step Video below along with the Code above can save your time.
Recommended Next Reading :
.25 semaglutide
.25 semaglutide
protonix 40 mg
protonix 40 mg
what are the side effects of robaxin
what are the side effects of robaxin
abilify success stories
abilify success stories
metformin repaglinide combination
metformin repaglinide combination
actos bloomberg
actos bloomberg
what is remeron used for
what is remeron used for
acarbose india
acarbose india
celecoxib generic
celecoxib generic
bupropion mechanism of action
bupropion mechanism of action
generic celebrex name
generic celebrex name
side effects of stopping celexa
side effects of stopping celexa
how does buspar work
how does buspar work
[augmentin].
[augmentin].
aripiprazole side effects weight gain
aripiprazole side effects weight gain
aspirin 81 mg
aspirin 81 mg
amitriptyline dosage for sleep reviews
amitriptyline dosage for sleep reviews
allopurinol contraindication
allopurinol contraindication
can i take amoxicillin on an empty stomach
can i take amoxicillin on an empty stomach
contrave 1 month results stories
contrave 1 month results stories
does effexor cause weight loss
does effexor cause weight loss
diltiazem hydrochloride
diltiazem hydrochloride
diclofenac sodium gel
diclofenac sodium gel
ddavp po dose
ddavp po dose
cozaar manufacturer
cozaar manufacturer
what are the side effects of depakote
what are the side effects of depakote
ezetimibe manufacturers in india
ezetimibe manufacturers in india
flomax for women side effects
flomax for women side effects
flexeril side effects
flexeril side effects
augmentin rash
augmentin rash
citalopram side effects 10mg
citalopram side effects 10mg
how long does bactrim take to work for uti
how long does bactrim take to work for uti
is bactrim an antibiotic
is bactrim an antibiotic
cephalexin dosage for skin infection
cephalexin dosage for skin infection
does ciprofloxacin expire
does ciprofloxacin expire
duloxetine loss of appetite
duloxetine loss of appetite
gabapentin onmeda
gabapentin onmeda
over the counter viagra in usa
over the counter viagra in usa
para que sirve el fluoxetine
para que sirve el fluoxetine
how long does lexapro take to work for anxiety
how long does lexapro take to work for anxiety
can keflex cause diarrhea
can keflex cause diarrhea
cymbalta patient assistance
cymbalta patient assistance
cephalexin and multivitamins
cephalexin and multivitamins
alternative to zoloft
alternative to zoloft
metronidazole galderma
metronidazole galderma
bupropion escitalopram
bupropion escitalopram
olympia pharmacy semaglutide
olympia pharmacy semaglutide
rybelsus diarrhea
rybelsus diarrhea
semaglutide vs wegovy
semaglutide vs wegovy
lisinopril maoi
lisinopril maoi
lasix seizures
lasix seizures
glucophage maigrire
glucophage maigrire
valtrex 1500
valtrex 1500
pregabalin diabetic neuropathy
pregabalin diabetic neuropathy
nolvadex menstruation
nolvadex menstruation
bactrim cymbalta
bactrim cymbalta
gabapentin meloxicam
gabapentin meloxicam
flagyl cleocin
flagyl cleocin
buy liquid tadalafil
buy liquid tadalafil
cialis patent expiration date
cialis patent expiration date
is tadalafil as good as cialis
is tadalafil as good as cialis
cialis sublingual
cialis sublingual
viagra 100mg tablet buy online
viagra 100mg tablet buy online
can you buy viagra over the counter in europe
can you buy viagra over the counter in europe
best generic viagra online
best generic viagra online
buy generic viagra online in usa
buy generic viagra online in usa
viagra 100mg tablet price in india
viagra 100mg tablet price in india
canadian viagra prescription
canadian viagra prescription
cialis softabs online
cialis softabs online
pharmacy online ventolin
pharmacy online ventolin
viagra 100mg canadian pharmacy
viagra 100mg canadian pharmacy
tadalafil 40 mg dosage
tadalafil 40 mg dosage
cheap viagra australia paypal
cheap viagra australia paypal
how long does tadalafil last
how long does tadalafil last
Confido
Confido
discount pharmacy tadalafil
discount pharmacy tadalafil
buy cialis fast shipping
buy cialis fast shipping
cialis australia online
cialis australia online
cost of sildenafil 30 tablets
cost of sildenafil 30 tablets
viagra price list
viagra price list
tadalafil mechanism of action in bph
tadalafil mechanism of action in bph
generic viagra professional 100mg
generic viagra professional 100mg
generic cialis
generic cialis
canadian pharmacy viagra pills
canadian pharmacy viagra pills
cialis 10mg daily
cialis 10mg daily
what does generic cialis look like
what does generic cialis look like
buy viagra online uk
buy viagra online uk
cialis didnt work
cialis didnt work
albendazole online pharmacy
albendazole online pharmacy
Viagra Oral Jelly
SECURING WEBAPI USING JSON WEB TOKEN (JWT) IN WEB API C# – DecatechLabs
mebendazole uk pharmacy
SECURING WEBAPI USING JSON WEB TOKEN (JWT) IN WEB API C# – DecatechLabs
bupropion target pharmacy
SECURING WEBAPI USING JSON WEB TOKEN (JWT) IN WEB API C# – DecatechLabs
online pharmacy hydrocodone reviews
SECURING WEBAPI USING JSON WEB TOKEN (JWT) IN WEB API C# – DecatechLabs
narrative essay help
SECURING WEBAPI USING JSON WEB TOKEN (JWT) IN WEB API C# – DecatechLabs
custom essay online
SECURING WEBAPI USING JSON WEB TOKEN (JWT) IN WEB API C# – DecatechLabs
custom writing essays
SECURING WEBAPI USING JSON WEB TOKEN (JWT) IN WEB API C# – DecatechLabs
descriptive essay help
SECURING WEBAPI USING JSON WEB TOKEN (JWT) IN WEB API C# – DecatechLabs
someone to write my essay
SECURING WEBAPI USING JSON WEB TOKEN (JWT) IN WEB API C# – DecatechLabs
essay title help
SECURING WEBAPI USING JSON WEB TOKEN (JWT) IN WEB API C# – DecatechLabs
how to write my essay
SECURING WEBAPI USING JSON WEB TOKEN (JWT) IN WEB API C# – DecatechLabs
essay writing service legit
SECURING WEBAPI USING JSON WEB TOKEN (JWT) IN WEB API C# – DecatechLabs
custom essay company
SECURING WEBAPI USING JSON WEB TOKEN (JWT) IN WEB API C# – DecatechLabs
help with essay papers
SECURING WEBAPI USING JSON WEB TOKEN (JWT) IN WEB API C# – DecatechLabs
write my social work essay
SECURING WEBAPI USING JSON WEB TOKEN (JWT) IN WEB API C# – DecatechLabs
community service essay
SECURING WEBAPI USING JSON WEB TOKEN (JWT) IN WEB API C# – DecatechLabs
essay writer cheap
SECURING WEBAPI USING JSON WEB TOKEN (JWT) IN WEB API C# – DecatechLabs
the best essay writing services
SECURING WEBAPI USING JSON WEB TOKEN (JWT) IN WEB API C# – DecatechLabs
viagra for sale on line
SECURING WEBAPI USING JSON WEB TOKEN (JWT) IN WEB API C# – DecatechLabs
This was a very informative read, Thank you! A service we offer:
https://vinaytechhouse.com/azure-data-factory-course-training-in-hyderabad/
Lick your way down http://tiny.cc/gz35vz
Tadalafil tablets https://the-dots.com/projects/drugstore-online-shopping-889086/
Thank you. Very good stuff!
Please fuck me https://is.gd/dBsd60
Waiting patiently for you to come home and fuck me! http://bitly.ws/znHX
Thanks you vary much for your efforts for crating JWT authentication tutorial.
Hi, can you tell me how to implement sliding expiration
https://decatechlabs.com/oauth2-refresh-token —– in this article you can update code at /refreshtoken endpoint and always create a new refresh token
Hi. This is very nice and helpful tutorial. Just one question, What will be the method to refresh the token after token expire? By passing old token can we refresh token and recrate it again?
I am glad it was helpful. I have not had a chance to write the refresh token workflow but I do have a code on my local machine that implements it if you are interested in I can share it.
so basically idea is that when you initially generate the token you save it in the database.
when it expires you use the expired token compared it with what is in the database to validate if it is a valid token and then you generate the new token. I do have a code for that using SQL server I think I wrote a few months back.
Great. I am storing this token in angular local storage instead of SQL. Please share the code so that I can re-write it according to my angular storage. Thank you very much.
Hello Apollo,
Do you happen to have any sample using RS256 instead of HMAC256??
Best Regards!!!
How do you lock down .html, .js, .css, and .png files using JWT?
Hi! Nice post!
I have one question… What if you set “expires” to null?
Hello, oscar I will have to test it to see the actual behavior but my educated guess will because expire specify when the token will expire so if you set it to null it will probably be valid all the time
Thank you so much, this tutorial was very helpful.
One question when the token expires I get a white screen (no error code). Is there a way to return a message when the token expires?
When the token expire the control hit this exception section and the return status is set to unauthorized. if you using postman you will see the status of request will be 401 unauthorized not 200 which mean OK.
you can use a content property to pass in additional message after token is rendered invalid.
Two ways to do it
return new HttpResponseMessage( HttpStatusCode.OK ) {Content = new StringContent( “Your message here” ) };
or for json serialized content
return new HttpResponseMessage( HttpStatusCode.OK ) {Content = new StringContent( SerializedString, System.Text.Encoding.UTF8, “application/json” ) };
In short this is change you will need to make .
inside the file TokenValidationHandler.cs –> SendAsync method last line approx#87 would become
like below
return Task.Factory.StartNew(() => new HttpResponseMessage(statusCode) { Content = new StringContent("There was problem on server" +
"when verifying your authorization") });
Thank you so much.
Thank you so much maaan it really saved my day!!! After searching and researching whole day i found this and it was really helpful!
You are welcome @Nikhung I am glad it was helpful. If you need any more help or have any questions let me know. If you found it helpful you may share it with friends so other can benefit it from also. If you need a deeper understanding of JWT and it’s purpose here is the good guide
Major mistakes developers Make when they start learning about JWT and OAuth2 works
Hi from Thrive Themes!
this was really helpful . saved my day .
we are glad it was helpfull .