WebApi - ApiKey plus JWT

Maryan 26 Reputation points
2022-04-24T23:18:04.233+00:00

I completed a couple of projects that are implemented in C# .Net 6.0 MVC, and now I'm trying to do my first web API project. This WebApi is implemented in .Net 6.0, with JWT authorization.
Everything is working smoothly so far, the token is generated then I can use the endpoints. However, I want to create separate another MVC application that will have an admin dashboard to control the data. My question is: if I implement ApiKey authorization in the web API, wouldn't be a problem or have a conflict with the JWT authorization?

I have only one year of experience with C# .Net, please try to understand that my knowledge is limited.
Thank you for your help!

ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,199 questions
ASP.NET API
ASP.NET API
ASP.NET: A set of technologies in the .NET Framework for building web applications and XML web services.API: A software intermediary that allows two applications to interact with each other.
301 questions
0 comments No comments
{count} votes

Accepted answer
  1. Zhi Lv - MSFT 32,016 Reputation points Microsoft Vendor
    2022-04-25T02:05:35.5+00:00

    Hi @Maryan ,

    if I implement ApiKey authorization in the web API, wouldn't be a problem or have a conflict with the JWT authorization?

    If you directly implement APIKey authorization in the API (with JWT authorization), when using custom API-Key attribute with the [Authorize] attribute together, the controller or the action method will be configured both JWT authentication and API-Key validation, in the request header, it should contain both the JWT token and API-Key. If any of them are missing, it will display a 401 Unauthorized error.

    I assume you want to achieve that not matter use any of the authorization method (JWT or API Key), you could access the related action method, if that is the case, you could try to use the custom the Authorization attributes.

    For example: create a CustomAuthorization with the following code:

    [AttributeUsage(AttributeTargets.Class)]  
    public class CustomAuthorization : Attribute, IAuthorizationFilter  
    {   
        /// <summary>    
        /// This will Authorize User    
        /// </summary>    
        /// <returns></returns>    
        public void OnAuthorization(AuthorizationFilterContext filterContext)  
        {  
    
            if (filterContext != null)  
            {  
                //get the authorization header  
                Microsoft.Extensions.Primitives.StringValues authTokens;  
                filterContext.HttpContext.Request.Headers.TryGetValue("Authorization", out authTokens);  
    
                var _token = authTokens.FirstOrDefault();  
    
                if (_token != null)  
                {  
                    string authToken = _token;  
                    if (authToken != null)  
                    {  
                        if (IsValidToken(authToken))  
                        {  
                            filterContext.HttpContext.Response.Headers.Add("Authorization", authToken);  
                            filterContext.HttpContext.Response.Headers.Add("AuthStatus", "Authorized");  
    
                            filterContext.HttpContext.Response.Headers.Add("storeAccessiblity", "Authorized");  
    
                            return;  
                        }  
                        else  
                        {  
                            filterContext.HttpContext.Response.Headers.Add("Authorization", authToken);  
                            filterContext.HttpContext.Response.Headers.Add("AuthStatus", "NotAuthorized");  
    
                            filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;  
                            filterContext.HttpContext.Response.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = "Not Authorized";  
                            filterContext.Result = new JsonResult("NotAuthorized")  
                            {  
                                Value = new  
                                {  
                                    Status = "Error",  
                                    Message = "Invalid Token"  
                                },  
                            };  
                        }  
    
                    }  
    
                }  
                else  
                {  
                    //if the request header doesn't contain the authorization header, try to get the API-Key.  
                    Microsoft.Extensions.Primitives.StringValues apikey;  
                    var key = filterContext.HttpContext.Request.Headers.TryGetValue("ApiKey", out apikey);  
                    var keyvalue = apikey.FirstOrDefault();  
    
                    //if the API-Key value is not null. validate the API-Key.  
                    if(keyvalue != null)  
                    {  
                        filterContext.HttpContext.Response.Headers.Add("ApiKey", keyvalue);  
                        filterContext.HttpContext.Response.Headers.Add("AuthStatus", "Authorized");  
    
                        filterContext.HttpContext.Response.Headers.Add("storeAccessiblity", "Authorized");  
    
                        return;  
                    }  
    
                      
                    filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized;  
                    filterContext.HttpContext.Response.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = "Please Provide authToken";  
                    filterContext.Result = new JsonResult("Please Provide auth Token")  
                    {  
                        Value = new  
                        {  
                            Status = "Error",  
                            Message = "Please Provide auth Token"  
                        },  
                    };    
                }  
            }  
        }  
    
        public bool IsValidToken(string authToken)  
        {  
            //validate Token here    
            return true;  
        }  
    }  
    

    Then, use the above CustomAuthorization in the API controller:

    [Route("api/[controller]")]  
    [ApiController]  
    //[Authorize]  
    //[ApiKey]  
    [CustomAuthorization]  
    public class ValuesController : ControllerBase  
    {  
        // GET: api/<ValuesController>  
        [HttpGet]  
        public IEnumerable<string> Get()  
        {  
            return new string[] { "value1", "value2" };  
        }  
    

    The result like this:

    KXW2D.gif

    Refer this article.

    Besides, you could also consider group the action method based on the Authorization method, for the API-key related action method or controller, only add the custom API-Key attribute, for the action method needs to JWT authentication, just add the [Authorize] attribute.


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    Best regards,
    Dillion

    1 person found this answer helpful.
    0 comments No comments

0 additional answers

Sort by: Most helpful