Implementing a Redirect with Actions and Passing Data Back to Auth0

Overview

This article provides an example of how to pass data back to Auth0 when implementing a Redirect with Actions on the Application side.

The documentation on Pass information back to the Action includes an example of the Action to be used in Auth0 with the following information:

A signed session token should be used to send sensitive information back to Auth0.
The token will be validated to ensure that:

  • The signature is valid.
  • The token is not expired.
  • The state claim within the token matches the state parameter used as part of the redirect.

To avoid replay attacks, the token should be sent back to Auth0 by making a POST request to the /continue endpoint. The tokenParameterName option in the code allows you to specify the name of the field that contains your token.

Solution

The following is an example of how to implement this within an application in .NET Core. However, it is possible to use a similar approach with any other backend language or framework as well.

Regular Web App

Parting from the ASP.NET Core MVC quickstart, the following changes were made to get the Action redirection working in a test app:

  1. Create a Controller: Create a controller, for example, AuthController, and add an action named Redirect
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Text;
using Microsoft.IdentityModel.Tokens;
using SampleMvcApp.ViewModels;
using System.Security.Claims;

namespace SampleMvcApp.Controllers
{
    public class AuthController : Controller
    {
        private readonly IConfiguration _configuration;

        public AuthController(IConfiguration configuration)
        {
            _configuration = configuration;
        }

        public IActionResult Redirect(string state, string session_token)
        {
            try
            {
                var tokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = true,
                    ValidIssuer = _configuration["Jwt:Issuer"],
                    ValidateAudience = false,
                    ValidateLifetime = true,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:SecretKey"])),
                    ClockSkew = TimeSpan.Zero
                };

                var handler = new JwtSecurityTokenHandler();
                var jsonToken = handler.ReadToken(session_token) as JwtSecurityToken;

                if (jsonToken == null)
                {
                    throw new SecurityTokenException("Invalid JWT token");
                }

                var tokenDescriptor = new SecurityTokenDescriptor
                {
                    Issuer = jsonToken.Issuer,
                    Expires = jsonToken.ValidTo,
                    SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:SecretKey"])), SecurityAlgorithms.HmacSha256),
                    Subject = new ClaimsIdentity(new[]
                    {
                        new Claim("state", state),
                        new Claim("sub", jsonToken.Subject)
                    })
                };

                var token = handler.CreateToken(tokenDescriptor);

                return View("Redirect", new RedirectViewModel
                {
                    State = state,
                    SessionToken = handler.WriteToken(token)
                });
            }
            catch (Exception ex)
            {
                // Handle exception
                Console.WriteLine(ex);
                throw new Exception("Token could not be decoded", ex);
            }
        }
    }
}
  1. Create a ViewModel: Create a ViewModel class to hold the data to be passed to the view.
using System;
namespace SampleMvcApp.ViewModels
{
    public class RedirectViewModel
    {
        public string State { get; set; }
        public string SessionToken { get; set; }
    }

}
  1. Create a View: Create a view file named Redirect.cshtml in the Views/Auth folder (or any other folder you prefer).
@using SampleMvcApp.ViewModels
@model RedirectViewModel

<h1>Loading...</h1>

<form id="redirectForm" method="post" action="https://YOUR-AUTH0-DOMAIN/continue?state=@Model.State">;
    <input type="hidden" name="state" value="@Model.State" />
    <input type="hidden" name="session_token" value="@Model.SessionToken" />
</form>

<script>document.getElementById('redirectForm').submit();</script>
  1. Configure JWT Settings in appsettings.json: Ensure you have the JWT settings configured in your appsettings.json file.
{
...
"Jwt": {
    "Issuer": "YOUR-AUTH0-DOMAIN",
    "SecretKey": "RANDOM-256-BITS-SECRET"
  }
}

That should be enough to get the Action Redirect working.