Azure App Service Custom Authentication

In this article, I will explain the concepts for Azure App Service Custom Authentication and provide sample code for the corresponding server side project.

Azure App Service Authentication is a feature that provides turnkey solutions for mobile & web apps to authenticate users with very minimal development efforts . It uses federated identity, in which a third-party identity provider stores accounts and authenticates users. Azure App Service supports five identity providers out of the box: Azure Active Directory, Facebook, Google, Microsoft Account & Twitter. Under the hood, the authentication process works as show in the diagram below:

Azure App Service Authentication Process

Authentication Process

1.The user signs in with one of the built-in authentication mechanisms, say Google.
2.The authentication request is forwarded to the identity provider
3.The identity provider authenticates the user and relays this to the Azure App Service
4.Upon successful authentication, Azure App Service will generate a token that will uniquely identifies the user for the application. We will be using the Json Web Token (JWT) approach provided by ASP.Net Core to achieve this functionality.
5.The token is then received by the web/app client. The client provides this token with every further request that it makes as a HTTP header (x-zumo-auth). 
6.When a request is received by Azure App service, it examines the supplied token and validates it- if the token is valid, the request is processed else a 401, un-authorized error is returned. The request method that needs to be secured only needs to have the attribute [Authorize] to enable this feature. Azure App Service internally receives the token from header and decrypts it to fetch claims.

In some situations, the social or enterprise flows provided by Azure App Service might not suffice your requirements as you might be relying upon a custom identity solution. For e.g, your application could be authenticating users against an identity store maintained in a custom database table. Fortunately, Azure App Service provides the ability to handle such scenarios as well. App developers can build their own custom authentication solution, still taking advantage of token validation feature provided by App Service.

Custom Authentication with Azure Mobile Apps

To demonstrate custom authentication , we will implement one of the most commonly used authentication scenarios — authenticating end users with username and password stored in a custom database. This will require to create a new Azure Mobile App back end project & write custom code to receive user credentials, generate and supply an authentication token to the client. The detailed steps and sample code is provided below:

  1. Create a new Azure Mobile App back-end project in Visual studio. This is where the custom authentication controller will be implemented and published to the Azure App Service.
  2. Install the Microsoft.Azure.Mobile.Server.Login package to assist with authentication token generation. This package contains the AppServiceLoginHandler.CreateToken method which allows to issue authentication tokens. The issued token may also include other claims and an expiry date.
  3. Provide your own code for validating user credentials. The custom authentication is exposed by creating an ApiController through the login action.
  4. The client should use a custom UI to collect the information from the user.The information is then submitted to the API with a standard HTTP POST call.
  5. Once the server validates the assertion, a token is issued using the AppServiceLoginHandler.CreateToken() method.

Login Action Example code

Download the starter Azure App Service backend code from your Azure App Service and modify it to include the login Action code.

mySigningKey: Every Azure Mobile App instance has a unique signing key which is automatically set and can be retrieved by Environment.GetEnvironmentVariable("WEBSITE_AUTH_SIGNING_KEY”)
myAppURL: Azure App Service Endpoint
Timespan: validity period of the token in hours.
using System;
using System.IdentityModel.Tokens;
using System.Security.Claims;
using System.Web.Http;
using System.Web.Http.OData.Extensions;
using Microsoft.Azure.Mobile.Server.Config;
using Microsoft.Azure.Mobile.Server.Login;
using Newtonsoft.Json.Linq;
namespace CustomAuthService.Controllers
{
[MobileAppController]
[Route(".auth/customAuth/login")] //Define the endpoint for the client to authenticate and request for a token
public class CustomAuthenticationController : ApiController
{
private string mySigningKey = Environment.GetEnvironmentVariable("WEBSITE_AUTH_SIGNING_KEY”)
private string myAppURL= "https://xyz.azurewebsites.net/"; //the URI should have a "/" at the end or else the authentication mechanism not work
public IHttpActionResult Post([FromBody] JObject assertion)
{
//Assertion is the JSON object received from the client in the POST body
if (assertion == null || assertion["username"] == null || assertion["password"] == null ||
assertion["username"].ToString().Length == 0 || assertion["username"].ToString().Length == 0)
{
return BadRequest();
}
//Create a new claim
var claims = new Claim[]
{
new Claim(JwtRegisteredClaimNames.Sub,assertion["username"].ToString())
};
if (isValidAssertion(assertion)) // user-defined function, checks against a database etc.
{
//Use JWT to create a new Token based
JwtSecurityToken token = AppServiceLoginHandler.CreateToken(claims,
mySigningKey,
myAppURL,
myAppURL,
TimeSpan.FromHours(24));
return Ok(new LoginResult()
// The LoginResult and LoginResultUser classes below provide the response to the client, when serialized by the JSON serializer.
                {
AuthenticationToken = token.RawData,
User = new LoginResultUser()
{
UserId = assertion["username"].ToString()
}
});
}
else // user assertion was not valid
{
return Unauthorized();
}
}
private bool isValidAssertion(JObject assertion)
{
string username = assertion["username"].ToString();
string password = assertion["password"].ToString();
if (username == "client_username" & password == "client_password)
return true;
else
return false;
}
// Sample Get API Method for testing the authentication 
[Authorize]
public string Get()
{
return "Hello from custom controller!";
}
}
}

You can support the standard client loginAsync() method by overloading the authentication route. If the client calls client.loginAsync('login'); to log -in, your route must be /.auth/customAuth/login.

To secure any controller/endpoint we need to add [Authorize] to those methods or controllers that need to be protected. For example:

[MobileAppController]
public class MyProtectedEndPoint : ApiController
{
[Authorize]
public string MyProtectedMethod()
{
return "this is a protected method";
}
}

Login responses sent to the client

{
"authenticationToken": "<token>",
"user": {
"userId": "<userId>"
}
}

How to use the token on the client

Before a user can access a secured resource/method, the authentication endpoint must be called in order to receive a token. Once a token is received, it should be supplied in the HTTP header [x-zumo-auth] alongwith every request to the service.

You can also test it using a REST client such as POSTMAN:

HTTP Post to authenticate and receive a JWT Token ( inset of the picture shows the request body)
Securing endpoints- passing the token as part of HTTP header
One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.