How to use OAuth (Bearer Token) Authentication in Azure Functions
This article help you to understand how bearer token is validating in your azure function.
First you need to understand what is the Bearer token?
"Bearer Token is used to authenticate your API's and token is in base 64 URL encoded value, some servers will issue tokens that are a short string of hexadecimal characters, while others may use structured tokens such as JSON Web Tokens. for more details on Bearer token click here.
Note: Bearer Token should be send via request headers to your azure function.
using Microsoft.IdentityModel.Protocols;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;
namespace AzureMediaServices
{
public static class BearerTokenValidation
{
public static async Task<bool> TokenIsValidAsync(string token, ILogger log)
{
try
{
bool isValidToken = true;
var tokenServerEndpoint = "https://login.microsoftonline.com/<Your TenantId>/"; //
var issuer = "https://sts.windows.net/<Your TenantId>"; //
First you need to understand what is the Bearer token?
"Bearer Token is used to authenticate your API's and token is in base 64 URL encoded value, some servers will issue tokens that are a short string of hexadecimal characters, while others may use structured tokens such as JSON Web Tokens. for more details on Bearer token click here.
Note: Bearer Token should be send via request headers to your azure function.
Validate your Bearer Token:
- First Create Application ID in Azure Active directory and generate client id & secrete and reply url. Click here to understand how to create app id in Azure active directory.
- Next create a Azure Http trigger function and add below code in your function.
public async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req, ILogger log)
{
var headers = req.Headers;
if (headers.TryGetValue("Authorization", out var authHeader))
{
if (authHeader[0].StartsWith("Bearer "))
{
token = authHeader[0].Substring(7, authHeader[0].Length - 7);
}
else
{
return new UnauthorizedResult();
}
bool isValidToken = await BearerTokenValidation.TokenIsValidAsync(token, log);
if (!isValidToken)
return new UnauthorizedResult();
}
}
- Create new class file and add below code
using Microsoft.IdentityModel.Protocols;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;
namespace AzureMediaServices
{
public static class BearerTokenValidation
{
public static async Task<bool> TokenIsValidAsync(string token, ILogger log)
{
try
{
bool isValidToken = true;
var tokenServerEndpoint = "https://login.microsoftonline.com/<Your TenantId>/"; //
var issuer = "https://sts.windows.net/<Your TenantId>"; //
var audiences = "Your AppID redirect/reply url";//
var keys = await GetSecurityKeysAsync(tokenServerEndpoint, log);
var validationParameters = new TokenValidationParameters
{
ValidIssuer = issuer,
ValidAudiences = new[] { audiences },
IssuerSigningKeys = keys
};
//Grab the claims from the token.
var handler = new JwtSecurityTokenHandler();
ClaimsPrincipal principal;
try
{
principal = handler.ValidateToken(token, validationParameters, out SecurityToken validatedToken);
return isValidToken;
}
catch (SecurityTokenExpiredException ex)
{
return isValidToken = false;
}
catch (Exception ex)
{
return isValidToken = false;
}
}
catch (Exception ex)
{
var keys = await GetSecurityKeysAsync(tokenServerEndpoint, log);
var validationParameters = new TokenValidationParameters
{
ValidIssuer = issuer,
ValidAudiences = new[] { audiences },
IssuerSigningKeys = keys
};
//Grab the claims from the token.
var handler = new JwtSecurityTokenHandler();
ClaimsPrincipal principal;
try
{
principal = handler.ValidateToken(token, validationParameters, out SecurityToken validatedToken);
return isValidToken;
}
catch (SecurityTokenExpiredException ex)
{
return isValidToken = false;
}
catch (Exception ex)
{
return isValidToken = false;
}
}
catch (Exception ex)
{
return false;
}
}
// Get the public keys from the jwks endpoint
private static async Task<ICollection<SecurityKey>> GetSecurityKeysAsync(string idpEndpoint, ILogger log)
{
try
{
var openIdConfigurationEndpoint = $"{idpEndpoint}.well-known/openid-configuration";
var configurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(openIdConfigurationEndpoint, new OpenIdConnectConfigurationRetriever());
var openIdConfig = await configurationManager.GetConfigurationAsync(CancellationToken.None);
return openIdConfig.SigningKeys;
}
catch(Exception ex)
{
return null;
}
}
}
}
}
}
// Get the public keys from the jwks endpoint
private static async Task<ICollection<SecurityKey>> GetSecurityKeysAsync(string idpEndpoint, ILogger log)
{
try
{
var openIdConfigurationEndpoint = $"{idpEndpoint}.well-known/openid-configuration";
var configurationManager = new ConfigurationManager<OpenIdConnectConfiguration>(openIdConfigurationEndpoint, new OpenIdConnectConfigurationRetriever());
var openIdConfig = await configurationManager.GetConfigurationAsync(CancellationToken.None);
return openIdConfig.SigningKeys;
}
catch(Exception ex)
{
return null;
}
}
}
}
Comments
Post a Comment