Alpha state. A platform designed for building enterprise-grade, multi-tenant products using Azure, .NET, React, TypeScript, Infrastructure as Code, etc.
Introduce a comprehensive token-based authentication system to handle One-Time Password (OTP) logins, as well as the issuing and validation of Refresh and Access Tokens (RT/AT). The Account Management self-contained system is responsible for generating the tokens, while the AppGateway intercepts all API calls, fetches the tokens from cookies, and manages the authentication flow.
If the Access Token is valid, the AppGateway forwards it as a Bearer token to the respective self-contained system API running behind the reverse proxy gateway. If the Access Token has expired, the AppGateway uses the Refresh Token to call a refresh endpoint in the Account Management system, obtaining a new Access Token before proceeding. This ensures a seamless and secure authentication experience.
To support this setup, a 64-bit signing key is generated by the Aspire AppHost on localhost and stored in .NET user secrets, enabling all self-contained systems to validate Access Tokens. In production, a 2048-bit RSA key is generated by Bicep and stored in KeyVault. Depending on the environment, either the DevelopmentTokenSigningService or the AzureTokenSigningService is used to sign and validate tokens.
The Access Token is valid for 5 minutes and is stored in a session cookie with strict security settings, while the Refresh Token, valid for 3 months, is stored in a separate cookie. The Access Token contains essential user information, such as name, title, avatar URL, and TenantID, which is also injected as an HTML meta tag for frontend use.
The Refresh Token is designed to minimize security risks, using several key elements:
JTI (JSON Web Token ID): A unique identifier that changes with each token issuance, ensuring that each token is distinct.
RefreshTokenID: An identifier used to track the specific Refresh Token, helping detect potential replay attacks.
RefreshVersion: This version is incremented each time a Refresh Token is used to issue a new Access Token, further enhancing the ability to detect and prevent replay attacks. The system is prepared to log and handle cases where a token’s version does not match the expected version, which could indicate an attempt to reuse an old token.
Additional Changes:
The existing Account Registration flow and endpoints have been renamed to Signup, with the /signup endpoint replacing /register.
The Single Page Application (SPA) has been updated to handle login and logout flows, including implementing the existing OTP login screen to generate an OTP, ensuring it cannot be brute-forced. This logic mirrors the existing Signup flow.
All API endpoints now require authentication by default, with AllowAnonymous explicitly set on endpoints that do not require authentication.
Tests have been updated to support authenticated calls.
The Shared WebApp has been updated with centralized logic for login and signup paths. The AuthenticationProvider has been simplified to support this streamlined approach.
The Avatar Menu has been enhanced to display user initials even when only the first name or last name is provided. Additionally, when the Update User Profile dialog is saved, the Access Token is refreshed to ensure the UI reflects the latest user information.
Bicep scripts have been added to create KeyVault RSA keys, including granting all self-contained systems read access to these keys. Issuer and Audience secrets have also been centralized in KeyVault, although they are not truly secrets.
Checklist
[x] I have added a Label to the pull-request
[x] I have added tests, and done manual regression tests
[x] I have updated the documentation, if necessary
Summary & Motivation
Introduce a comprehensive token-based authentication system to handle One-Time Password (OTP) logins, as well as the issuing and validation of Refresh and Access Tokens (RT/AT). The Account Management self-contained system is responsible for generating the tokens, while the AppGateway intercepts all API calls, fetches the tokens from cookies, and manages the authentication flow.
If the Access Token is valid, the AppGateway forwards it as a Bearer token to the respective self-contained system API running behind the reverse proxy gateway. If the Access Token has expired, the AppGateway uses the Refresh Token to call a refresh endpoint in the Account Management system, obtaining a new Access Token before proceeding. This ensures a seamless and secure authentication experience.
To support this setup, a 64-bit signing key is generated by the Aspire AppHost on localhost and stored in .NET user secrets, enabling all self-contained systems to validate Access Tokens. In production, a 2048-bit RSA key is generated by Bicep and stored in KeyVault. Depending on the environment, either the
DevelopmentTokenSigningService
or theAzureTokenSigningService
is used to sign and validate tokens.The Access Token is valid for 5 minutes and is stored in a session cookie with strict security settings, while the Refresh Token, valid for 3 months, is stored in a separate cookie. The Access Token contains essential user information, such as name, title, avatar URL, and TenantID, which is also injected as an HTML meta tag for frontend use.
The Refresh Token is designed to minimize security risks, using several key elements:
Additional Changes:
Checklist