# Strapi Plugin - Azure AD SSO

Enterprise-grade Azure AD (Microsoft Entra ID) Single Sign-On plugin for Strapi with automatic role assignment.

## Features

- 🔐 **Azure AD OAuth 2.0** - Secure authentication with native PKCE flow
- 🎭 **Automatic Role Assignment** - Map Azure AD groups to Strapi admin roles
- 🚀 **Modern Implementation** - Built for Strapi v5+ with zero external auth dependencies
- ⚡ **Zero Password Management** - Users authenticate via Microsoft
- 🔒 **Enterprise Security** - State validation, native PKCE, and secure token handling
- 📦 **Lightweight** - Native crypto implementation, no heavy dependencies

## Installation

```bash
npm install strapi-plugin-sso-azuread
```

## Configuration

### 1. Azure AD Setup

1. Go to [Azure Portal](https://portal.azure.com)
2. Navigate to **Azure Active Directory** > **App registrations**
3. Click **New registration**
4. Configure:
   - **Name**: Your Strapi App
   - **Supported account types**: Single tenant (recommended)
   - **Redirect URI**: `https://your-domain.com/sso-azuread/callback`
5. After creation, note the **Application (client) ID** and **Directory (tenant) ID**
6. Go to **Certificates & secrets** > **New client secret**
7. Save the secret value

### 2. Strapi Configuration

Add to your `config/plugins.js` (or `config/plugins.ts`):

```javascript
module.exports = ({ env }) => ({
  // ... other plugins
  'sso-azuread': {
    enabled: true,
    config: {
      AZUREAD_TENANT_ID: env('AZUREAD_TENANT_ID'),
      AZUREAD_OAUTH_CLIENT_ID: env('AZUREAD_OAUTH_CLIENT_ID'),
      AZUREAD_OAUTH_CLIENT_SECRET: env('AZUREAD_OAUTH_CLIENT_SECRET'),
      AZUREAD_OAUTH_REDIRECT_URI: env('AZUREAD_OAUTH_REDIRECT_URI', 'http://localhost:1337/sso-azuread/callback'),
      AZUREAD_SCOPE: env('AZUREAD_SCOPE', 'openid profile email'),
      
      // Optional: Restrict access to specific Azure AD groups
      AZUREAD_ALLOWED_GROUPS: env.array('AZUREAD_ALLOWED_GROUPS', []),
      
      // Optional: Auto-create users on first login
      AUTO_CREATE_USERS: env.bool('AZUREAD_AUTO_CREATE_USERS', true),
      
      // Optional: Default locale for new users
      DEFAULT_LOCALE: env('AZUREAD_DEFAULT_LOCALE', 'en'),
      
      // Optional: Remember me (stores JWT in localStorage)
      REMEMBER_ME: env.bool('AZUREAD_REMEMBER_ME', true),
    },
  },
});
```

### 3. Environment Variables

Add to your `.env`:

```env
AZUREAD_TENANT_ID=your-tenant-id
AZUREAD_OAUTH_CLIENT_ID=your-client-id

# Optional: Restrict to specific groups (comma-separated group IDs)
# Get group IDs from Azure Portal > Azure AD > Groups
AZUREAD_ALLOWED_GROUPS=group-id-1,group-id-2

AZUREAD_OAUTH_CLIENT_SECRET=your-client-secret
AZUREAD_OAUTH_REDIRECT_URI=http://localhost:1337/sso-azuread/callback
AZUREAD_SCOPE=openid profile email
AZUREAD_AUTO_CREATE_USERS=true
AZUREAD_DEFAULT_LOCALE=en
AZUREAD_REMEMBER_ME=true
```

## Usage

### User Login

Users can now log in via Azure AD:

1. Go to your Strapi admin panel
2. Click "Sign in with Azure AD" button
3. Authenticate with Microsoft credentials
4. Automatically redirected back to Strapi

### Configure Auto-Roles

1. Navigate to **Settings** > **Azure AD SSO** in the Strapi admin panel
2. Select which Strapi roles should be assigned to new users
3. Users logging in for the first time will automatically receive these roles

### Restrict Access to Specific Groups

To allow only users from specific Azure AD groups:

1. **In Azure Portal:**
   - Go to **App registrations** → Your app → **Token configuration**
   - Click **Add groups claim**
   - Select **Security groups**
   - Check all token types (ID, Access, SAML)

2. **Get Group IDs:**
   - Go to **Azure Active Directory** → **Groups**
   - Click on the group you want to allow
   - Copy the **Object ID**

3. **Configure in Strapi:**
   ```env
   # Add comma-separated group IDs
   AZUREAD_ALLOWED_GROUPS=12345678-1234-1234-1234-123456789012,87654321-4321-4321-4321-210987654321
   ```

4. **Test:** Users not in these groups will see "Access denied: You are not a member of an authorized group."

### Advanced: Group-Based Role Mapping

For enterprise scenarios where you want to map Azure AD groups to Strapi roles:

1. In Azure AD, configure your app to include group claims in tokens
2. Extend the plugin's autorole service to read group claims
3. Map specific Azure AD group IDs to Strapi role IDs

## API Endpoints

- `GET /sso-azuread/auth` - Initiates Azure AD login
- `GET /sso-azuread/callback` - OAuth callback handler
- `GET /sso-azuread/autorole` - Get current autorole configuration (admin only)
- `PUT /sso-azuread/autorole` - Update autorole configuration (admin only)

## Security
Native PKCE Flow**: Implements Proof Key for Code Exchange using Node.js crypto for enhanced security
- **State Validation**: Prevents CSRF attacks
- **Secure Sessions**: Uses HTTP-only session cookies
- **Nonce CSP**: Content Security Policy with nonces
- **Password Generation**: Users created with cryptographically secure random passwords (256-bit)
- **No External Auth Dependencies**: Uses native Node.js crypto module for all security operation
- **Password Generation**: Users created with cryptographically secure random passwords

## Troubleshooting

### "Email address is not set" error

Ensure your Azure AD users have email addresses configured. Go to Azure AD > Users and verify the email property.

### "Invalid state" error

This typically indicates a session issue. Ensure:
- Session middleware is properly configured in Strapi
- Cookies are enabled in your browser
- The redirect URI matches exactly (including protocol and port)

### Users not being created

Check:
- `AUTO_CREATE_USERS` is set to `true`
- The Azure AD user has a valid email address
- Your database is properly connected

## License

MIT

## Support

For issues and feature requests, please use the GitHub issue tracker.
