224 lines
No EOL
8.5 KiB
Markdown
224 lines
No EOL
8.5 KiB
Markdown
# MSAL PKCE Authentication Flow Specification
|
|
|
|
## Overview
|
|
|
|
This document specifies the Microsoft Authentication Library (MSAL) implementation with Proof Key for Code Exchange (PKCE) flow used in this web application. The implementation uses popup-based authentication with Azure AD/Entra ID and includes server-side JWT validation with httpOnly cookies for secure session management.
|
|
|
|
## Architecture Components
|
|
|
|
### Frontend Components
|
|
- **MSAL Browser Library**: `msal-browser.min.js` v2.15.0
|
|
- **Authentication Method**: Popup-based login with PKCE
|
|
- **Token Storage**: Session storage for MSAL tokens, httpOnly cookies for server sessions
|
|
- **Cache Configuration**: Session storage with fallback cookie for auth state
|
|
|
|
### Backend Components
|
|
- **Server-Side Validation**: Custom JWT validation using Firebase JWT library
|
|
- **Session Management**: httpOnly cookies with security headers
|
|
- **Token Validation**: Real-time validation against Azure AD public keys
|
|
- **Authentication Middleware**: Server-side protection for all routes
|
|
|
|
## Azure AD Configuration
|
|
|
|
### Application Registration
|
|
- **Client ID**: `9079054c-9620-4757-a256-23413042f1ef`
|
|
- **Tenant ID**: `e519c2e6-bc6d-4fdf-8d9c-923c2f002385`
|
|
- **Authority URL**: `https://login.microsoftonline.com/{tenantId}`
|
|
- **Application Type**: Single Page Application (SPA)
|
|
- **Authentication Flow**: Authorization Code with PKCE
|
|
- **Redirect URI**: Dynamic based on application origin
|
|
|
|
### Required Scopes
|
|
- `openid` - OpenID Connect authentication
|
|
- `profile` - User profile information
|
|
- `email` - User email address
|
|
|
|
## MSAL Configuration
|
|
|
|
### Client Configuration
|
|
```javascript
|
|
const msalConfig = {
|
|
auth: {
|
|
clientId: "9079054c-9620-4757-a256-23413042f1ef",
|
|
authority: "https://login.microsoftonline.com/e519c2e6-bc6d-4fdf-8d9c-923c2f002385",
|
|
redirectUri: window.location.origin + window.location.pathname.replace(/\/$/, '')
|
|
},
|
|
cache: {
|
|
cacheLocation: "sessionStorage",
|
|
storeAuthStateInCookie: true,
|
|
}
|
|
};
|
|
```
|
|
|
|
### Login Request Configuration
|
|
```javascript
|
|
const loginRequest = {
|
|
scopes: ["openid", "profile", "email"],
|
|
prompt: "select_account"
|
|
};
|
|
```
|
|
|
|
## Authentication Flow Steps
|
|
|
|
### 1. User Access Control
|
|
- **Server-Side Gate**: All pages require authentication via `AuthMiddleware->requireAuth()`
|
|
- **Unauthenticated Users**: Redirected to login interface automatically
|
|
- **Token Validation**: Every request validates JWT against Azure AD public keys
|
|
|
|
### 2. Login Initiation
|
|
1. User clicks "Sign In with Microsoft" button
|
|
2. `myMSALObj.loginPopup(loginRequest)` triggers PKCE flow
|
|
3. MSAL automatically generates PKCE code verifier and challenge
|
|
4. User redirected to Azure AD login in popup window
|
|
|
|
### 3. Azure AD Authentication
|
|
1. User authenticates with Microsoft credentials
|
|
2. Azure AD validates user and application permissions
|
|
3. Authorization code returned with PKCE validation
|
|
4. MSAL exchanges code for tokens using PKCE code verifier
|
|
|
|
### 4. Token Exchange and Validation
|
|
1. **Client receives tokens**: ID token and access token from MSAL
|
|
2. **Server submission**: Tokens sent to `auth.php` endpoint
|
|
3. **JWT validation**: Server validates token signature against Azure AD JWKS
|
|
4. **Claims validation**: Audience, issuer, expiration, and timing claims checked
|
|
5. **Cookie creation**: Valid tokens stored in httpOnly cookie with security flags
|
|
|
|
### 5. Session Management
|
|
1. **httpOnly cookie**: Prevents JavaScript access to authentication token
|
|
2. **Security flags**: Secure, SameSite=Lax, path=/, 24-hour expiration
|
|
3. **Server-side validation**: Every request validates cookie token
|
|
4. **Automatic renewal**: No automatic token refresh implemented
|
|
|
|
### 6. Logout Process
|
|
1. **Client logout**: `auth.php` called to clear server-side cookie
|
|
2. **MSAL logout**: `myMSALObj.logoutPopup()` clears client-side tokens
|
|
3. **Page reload**: Fresh page load to reflect authentication state
|
|
|
|
## Security Implementation
|
|
|
|
### Token Security
|
|
- **httpOnly cookies**: Prevent XSS access to authentication tokens
|
|
- **Secure flag**: Cookies only sent over HTTPS in production
|
|
- **SameSite protection**: CSRF protection with Lax policy
|
|
- **Server-side validation**: No client-side security dependencies
|
|
|
|
### JWT Validation Process
|
|
1. **JWKS retrieval**: Public keys fetched from Azure AD OpenID configuration
|
|
2. **Signature verification**: JWT signature validated using RS256 algorithm
|
|
3. **Claims validation**: Comprehensive validation of all standard claims
|
|
4. **Real-time validation**: Every request validates token freshness
|
|
|
|
### Supported Token Types
|
|
- **Primary**: ID tokens (preferred for user authentication)
|
|
- **Fallback**: Access tokens (Microsoft Graph audience)
|
|
- **Validation**: Both token types supported with appropriate audience validation
|
|
|
|
## Server-Side Components
|
|
|
|
### AuthMiddleware.php
|
|
- **Purpose**: Authentication gate for all protected resources
|
|
- **Methods**:
|
|
- `requireAuth()`: Enforce authentication for page access
|
|
- `isAuthenticated()`: Check current authentication status
|
|
- `setAuthToken()`: Store validated token in httpOnly cookie
|
|
- `clearAuthToken()`: Remove authentication cookie
|
|
|
|
### JWTValidator.php
|
|
- **Purpose**: Validate Azure AD JWT tokens server-side
|
|
- **Features**:
|
|
- Real-time JWKS key retrieval from Azure AD
|
|
- Comprehensive claims validation (exp, nbf, aud, iss)
|
|
- Support for multiple token audiences and issuers
|
|
- Firebase JWT library integration
|
|
|
|
### auth.php
|
|
- **Purpose**: Authentication endpoint for login/logout operations
|
|
- **Endpoints**:
|
|
- `POST /auth.php?action=login`: Process authentication tokens
|
|
- `POST /auth.php?action=logout`: Clear authentication session
|
|
- `GET /auth.php?action=status`: Check authentication status
|
|
|
|
## Error Handling
|
|
|
|
### Authentication Errors
|
|
- **Invalid tokens**: Clear error messages with retry options
|
|
- **Expired sessions**: Automatic redirect to login interface
|
|
- **Network errors**: Graceful fallback with user notifications
|
|
- **Popup blocking**: Error handling for blocked popup windows
|
|
|
|
### Server-Side Error Handling
|
|
- **Token validation failures**: Specific error messages logged and returned
|
|
- **JWKS retrieval errors**: Fallback mechanisms and retry logic
|
|
- **Cookie security**: Proper error responses for cookie failures
|
|
|
|
## Implementation Requirements
|
|
|
|
### Frontend Dependencies
|
|
- MSAL Browser library v2.15.0 or later
|
|
- Modern browser with popup support
|
|
- JavaScript ES6+ support
|
|
- Fetch API for token submission
|
|
|
|
### Backend Dependencies
|
|
- PHP 7.4+ with OpenSSL support
|
|
- Firebase JWT library via Composer
|
|
- cURL or file_get_contents for HTTPS requests
|
|
- Cookie support in server environment
|
|
|
|
### Azure AD Requirements
|
|
- Application registered as Single Page Application
|
|
- Redirect URIs configured for all deployment environments
|
|
- Appropriate API permissions granted
|
|
- PKCE support enabled (default for SPAs)
|
|
|
|
## Configuration Variables
|
|
|
|
### Required Environment Configuration
|
|
```php
|
|
// AuthMiddleware.php
|
|
private $tenantId = 'e519c2e6-bc6d-4fdf-8d9c-923c2f002385';
|
|
private $clientId = '9079054c-9620-4757-a256-23413042f1ef';
|
|
```
|
|
|
|
### Cookie Security Configuration
|
|
```php
|
|
$cookieOptions = [
|
|
'expires' => time() + (24 * 60 * 60), // 24 hours
|
|
'path' => '/',
|
|
'domain' => '',
|
|
'secure' => isset($_SERVER['HTTPS']), // HTTPS in production
|
|
'httponly' => true,
|
|
'samesite' => 'Lax'
|
|
];
|
|
```
|
|
|
|
## Testing and Validation
|
|
|
|
### Authentication Testing
|
|
1. **Successful login**: Verify popup authentication and cookie creation
|
|
2. **Token validation**: Confirm server-side JWT validation
|
|
3. **Session persistence**: Test page navigation with authentication
|
|
4. **Logout functionality**: Verify complete session termination
|
|
|
|
### Security Testing
|
|
1. **Cookie security**: Verify httpOnly and secure flags
|
|
2. **XSS protection**: Confirm no client-side token exposure
|
|
3. **Token expiration**: Test automatic session invalidation
|
|
4. **CSRF protection**: Verify SameSite cookie protection
|
|
|
|
## Migration Considerations
|
|
|
|
### From Basic MSAL Implementation
|
|
1. **Add server-side validation**: Implement JWT validation middleware
|
|
2. **Replace client-side token storage**: Move to httpOnly cookies
|
|
3. **Add authentication gates**: Protect all server endpoints
|
|
4. **Update error handling**: Implement proper fallback mechanisms
|
|
|
|
### Security Upgrades
|
|
1. **Remove client-side security**: Eliminate CSS-based protection
|
|
2. **Implement token validation**: Add real-time JWT verification
|
|
3. **Secure cookie implementation**: Use httpOnly with security flags
|
|
4. **Add comprehensive error handling**: User-friendly error messages
|
|
|
|
This specification provides a complete reference for implementing secure MSAL PKCE authentication with server-side validation and httpOnly cookie session management. |