0

I am trying to implement jwt token authentication in my web api. I have a front end app which is in angular 8. i want to save the token in cookie.how can i achieve this?? what will be the syntax for the subsequent call from the angular,if i save the token in cookie after login.

TokenValidationHandler

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;
    }
    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;
}
}

LoginController(will generate the token)

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=="pass" ? 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.AddSeconds(30);

    //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;
}
}

1 Answer 1

1

Firstly, the httponly cookie cannot be accessed from JavaScript.

Secondly, please refer to the code below to return the cookie along with the response.

private HttpResponseMessage setTokenCookie(LoginResponse response)
        {
            var responseMessage = Request.CreateResponse(HttpStatusCode.OK, response);

            var cookie = new CookieHeaderValue("token", response.Token)
            {
                Expires = DateTimeOffset.Now.AddDays(7),
                HttpOnly = true
            };

            responseMessage.Headers.AddCookies(new CookieHeaderValue[] { cookie });

            return responseMessage;
        }

You can use the function mentioned above in your controller action method as shown below to return the cookie.

var responseWithCookie = setTokenCookie(response);

return ResponseMessage(responseWithCookie);

I've assumed that LoginResponse class has Token property.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.