Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using JSON Web Tokens (JWT) with Azure Functions (WITHOUT using Active Directory)

I am sure someone out there has already done this, but I have yet to find any documentation with regard to the Microsoft implementation of JWT. The official documentation from Microsoft for their JWT library is basically an empty page, see:

https://docs.microsoft.com/en-us/dotnet/framework/security/json-web-token-handler-api-reference

So, here is what I (and I am sure many others) would like to accomplish:

Definition: User ID = The username or email address used to log into a system.

AUTHENTICATION:

  1. A user logs in. The user fills in web form and the system sends (via HTTPS POST) the users ID and password (hashed) to the server in order to authenticate / validate the user.

  2. Server Authenticates user. The users ID and password are checked against the values saved in the database and if NOT valid, an invalid login response is returned to the caller.

  3. Create a JWT Token - ???? No documentation available!

  4. Return the JWT token to the caller - ???? - I assume in a header? via JSON, not sure -- again - no documentation.

Given the code below, can anyone provide a code example for steps 3 and 4?

  [FunctionName( "authenticate" )]
  public static async Task<HttpResponseMessage> Run( [HttpTrigger( AuthorizationLevel.Anonymous, "get", "post", Route = null )]HttpRequestMessage req, TraceWriter log )
  {

   // Step 1 - Get user ID and password from POST data

   /*
   * Step 2 - Verify user ID and password (compare against DB values)
   * If user ID or password is not valid, return Invalid User response
   */

   // Step 3 - Create JWT token - ????

   // Step 4 - Return JWT token - ????

  }

AUTHORIZATION:

Assuming the user was authenticated and now has a JWT token (I am assuming the JWT token is saved in the users session; if someone wants to provide more info, please do):

  1. A POST request is made to an Azure Function to do something (like get a users birth date). The JWT token obtained above is loaded (from the POST data or a header - does it matter?) along with any other data required by the function.

  2. The JWT token is validated - ???? No documentation available!

  3. If the JWT token is NOT valid, a BadRequest response is returned by the function.

  4. If the JWT token is valid, the function uses the data passed to it to process and issue a response.

Given the code below, can anyone provide a code example for steps 1 and 2?

  [FunctionName( "do_something" )]
  public static async Task<HttpResponseMessage> Run( [HttpTrigger( AuthorizationLevel.Anonymous, "get", "post", Route = null )]HttpRequestMessage req, TraceWriter log )
  {

   // Step 1 - Get JWT token (from POST data or headers?)

   // Step 2 - Validate the JWT token - ???

   // Step 3 - If JWT token is not valid, return BadRequest response

   // Step 4 - Process the request and return data as JSON

  }

Any and all information would really help those of us (me) understand how to use JWT with Azure (anonymous) functions in order to build a "secure" REST API.

Thanks in advance.

like image 857
bdcoder Avatar asked Mar 07 '18 22:03

bdcoder


People also ask

Do JWT need to be stored in database?

JWTs can be used as an authentication mechanism that does not require a database. The server can avoid using a database because the data store in the JWT sent to the client is safe.

Is JWT good for API authentication?

JWT-based API auth is a good choice for securing microservices within an organization, or sharing APIs with certain types of external clients. JWT tokens are typically not revokable. To revoke a JWT token you typically have to roll the secrets of that client - this will disable ALL JWT tokens currently issued.


2 Answers

Any and all information would really help those of us (me) understand how to use JWT with Azure (anonymous) functions in order to build a "secure" REST API.

Per my understanding, you could use the related library in your azure function code to generate / validate the JWT token. Here are some tutorials, you could refer to them:

Create and Consume JWT Tokens in C#.

Jwt.Net, a JWT (JSON Web Token) implementation for .NET

JWT Authentication for Asp.Net Web Api

Moreover, you could leverage App Service Authentication / Authorization to configure the function app level Authentication / Authorization. You could go to your Function App Settings, click "NETWORKING > Authentication / Authorization" under the Platform features tab. Enable App Service Authentication and choose Allow Anonymous requests (no action) as follows:

enter image description here

You could create a HttpTrigger function with anonymous accessing for user logging and return the JWT token if the user exists. For the protected REST APIs, you could follow the code sample below:

if(System.Security.Claims.ClaimsPrincipal.Current.Identity.IsAuthenticated)
{
   //TODO: retrieve the username claim
   return req.CreateResponse(HttpStatusCode.OK,(System.Security.Claims.ClaimsPrincipal.Current.Identity as ClaimsIdentity).Claims.Select(c => new { key = c.Type, value = c.Value }),"application/json");
}
else
{
    return req.CreateResponse(HttpStatusCode.Unauthorized,"Access Denied!"); 
}

For generating the JWT token used in App Service Authentication, you could follow How to: Use custom authentication for your application and the code under custom API controller CustomAuthController from adrian hall's book about Custom Authentication to create the JWT token.

UPDATE:

For the custom authentication approach under App Service Authentication, I just want op to leverage the authentication / Authorization provided by EasyAuth. I have did some test for this approach and found it could work on my side. Op could send the username and password to the HttpTrigger for authentication, then the HttpTrigger backend need to validate the user info, and use Microsoft.Azure.Mobile.Server.Login package for issuing App Service Authentication token to the client, then the client could retrieve the token from the AuthenticationToken property. The subsequent requests against the protected APIs could look like as follows:

https://<your-funapp-name>.azurewebsites.net/api/<httpTrigger-functionName>
Header: x-zumo-auth:<AuthenticationToken>

NOTE:

For this approach, the related HttpTrigger functions need to allow anonymous accessing and the App Service Authentication also needs to choose Allow Anonymous requests (no action). Otherwise, the App Service Authentication and function level authentication would both validate the request. For the protected APIs, op needs to manually add the System.Security.Claims.ClaimsPrincipal.Current.Identity.IsAuthenticated checking.

like image 58
Bruce Chen Avatar answered Sep 18 '22 05:09

Bruce Chen


Try this: https://liftcodeplay.com/2017/11/25/validating-auth0-jwt-tokens-in-azure-functions-aka-how-to-use-auth0-with-azure-functions/ I successfully made it work using this guide. It took awhile due to nuget versions.

Follow that guide properly and use the following nuget versions

IdentityModel.Protocols (2.1.4)
IdentityModel.Protocols.OpenIdConenct (2.1.4)
IdentityModel.Tokens.Jwt (5.1.4)

Oh and, the guide tells you to write your AUDIENCE as your api link, don't. You'll get unauthorized error. Just write the name of your api, e.g. myapi

If you get error about System.http.formatting not being loaded when running the function, try to reinstall NET.Sdk.Functions and ignore the warning about AspNet.WebApi.Client being restored using .NETFramework. And restart visual studio.

like image 36
Charles Dickens Avatar answered Sep 20 '22 05:09

Charles Dickens