Asked by:
Return custom json response when Unauthorized / token expired

Question
-
User381809404 posted
Hi,
I have implemented one .net core API project where i am using JWT for token authorization and it works fine in case of correct token but if token is expired or Unauthorized access, it gives status code inside POSTMAN but i wanted to return json response in POSTMAN body to show custom json on my api call result.
You can check my source code.
Startup.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Tokens; namespace TestJWT { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidIssuer = "mysite.com", ValidateAudience = true, ValidAudience = "mysite.com", ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("sdfoiweklmnjlk2#lkjadsfms.dcizdsdlkfjls@!1@dfsdf")) }; }); services.AddMvc(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseAuthentication(); app.UseMvc(); } } }
AuthController
using System; using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.IdentityModel.Tokens; using System.Text; namespace TestJWT.Controllers { [Route("api/[controller]")] public class AuthController : Controller { [HttpPost("token")] public IActionResult Token() { string header = Request.Headers["Authorization"]; if (header.StartsWith("Basic")) { var credValue = header.Substring("Basic".Length).Trim(); var usernameAndPassenc = Encoding.UTF8.GetString(Convert.FromBase64String(credValue)); var userNameandPassword = usernameAndPassenc.Split(":"); if(userNameandPassword[0] == "Admin" && userNameandPassword[1] == "pswd") { //var claimsdata = new[] { new Claim(ClaimTypes.Name, "userName"), new Claim(ClaimTypes.Name, "userId") }; var claimsdata = new[] { new Claim(JwtRegisteredClaimNames.Sub, "Pritesh"), new Claim(JwtRegisteredClaimNames.Sub, "Mehta") }; var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("sdfoiweklmnjlk2#lkjadsfms.dcizdsdlkfjls@!1@dfsdf")); var signInCred = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature); var token = new JwtSecurityToken( issuer: "mysite.com", audience: "mysite.com", expires: DateTime.Now.AddMinutes(1), claims: claimsdata, signingCredentials: signInCred ); var tokenString = new JwtSecurityTokenHandler().WriteToken(token); return Ok(new { token = tokenString, id = userNameandPassword[1], expires = token.ValidTo }); } } return BadRequest("Wrong Request"); } } }
ValuesController
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; namespace TestJWT.Controllers { [Route("api/[controller]")] public class ValuesController : Controller { [Authorize] // GET api/values [HttpGet] public IEnumerable<string> Get() { return new string[] { "value1", "value2" }; } // GET api/values/5 [HttpGet("{id}")] public string Get(int id) { return "value"; } // POST api/values [HttpPost] public void Post([FromBody]string value) { } // PUT api/values/5 [HttpPut("{id}")] public void Put(int id, [FromBody]string value) { } // DELETE api/values/5 [HttpDelete("{id}")] public void Delete(int id) { } } }
Thank you.
Monday, August 6, 2018 9:32 AM
All replies
-
User475983607 posted
My best guess is you are asking how to return a custom 401 error? For some reason a 401 is not good enough?
Anyway, the ASP Core documentation explains how to handle custom error responses.
https://docs.microsoft.com/en-us/aspnet/core/fundamentals/error-handling?view=aspnetcore-2.1
You can format the response however you like.
Monday, August 6, 2018 11:20 AM -
User1634889493 posted
Realize it has been a while since you asked this question, but maybe this will still help someone. Here is what I'm trying and it seems to work.
public class ChallengeMiddleware { private static void writeErrorResponse(HttpContext Context, params string[] Errors) { Context.Response.ContentType = "application/json"; using (var writer = new Utf8JsonWriter(Context.Response.BodyWriter)) { writer.WriteStartObject(); writer.WriteBoolean("isValid", false); writer.WriteStartArray("errors"); foreach (var error in Errors) { writer.WriteStringValue(error); } writer.WriteEndArray(); writer.WriteEndObject(); writer.Flush(); } } private readonly RequestDelegate _request; public ChallengeMiddleware(RequestDelegate RequestDelegate) { if (RequestDelegate == null) { throw new ArgumentNullException(nameof(RequestDelegate) , nameof(RequestDelegate) + " is required"); } _request = RequestDelegate; } public async Task InvokeAsync(HttpContext Context) { if (Context == null) { throw new ArgumentNullException(nameof(Context) , nameof(Context) + " is required"); } await _request(Context); if(Context.Response.StatusCode == 401) { writeErrorResponse(Context, "Please log in"); } }
I'm injecting into the pipeline in the Configure method at this point:
.UseAuthentication() .UseMiddleware<ChallengeMiddleware>() <- custom middleware .UseAuthorization()
Sunday, July 12, 2020 2:38 AM