> ## Content Index
> Fetch the complete content index at: https://blog.fabrixly.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# How to Use Implicit Flow in Fabrixly-IDS
- URL: https://blog.fabrixly.com/how-to-use-implicit-flow/
- Published: 2026-07-07T03:08:38.000Z
- Updated: 2026-07-10T07:22:39.000Z
- Author: Fabrixly
- Tags: Documentation

## Overview

The Implicit Flow was designed for browser-based single-page apps (SPA) that can't keep a client secret secure. It returns tokens directly from the authorization endpoint.

⚠️ **Important**: Authorization Code Flow with PKCE is now recommended instead of Implicit Flow for SPAs! But we still support it for legacy apps.

## Step 1: Configure Implicit Flow Client

First, set up your OIDC client for implicit flow:

### Admin Console Setup

1. Go to **Fabrixly-IDS Admin Console** → **Clients**
2. Create or select client → click **Edit**
3. Under **OAuth/OIDC Settings**:
  - **Response Types**: add `id_token`, `token` (or both)
  - **Grant Types**: add `implicit`
  - **Token Endpoint Auth Method**: select `none`
  - **Auth Mode**: choose any auth mode you like
4. Save!

### API Setup

### Authenticating API Requests

Management API endpoints (like `/api/clients`, `/api/users`, etc.) require administrative authentication. To call them:

1. **Include the Token in the Authorization Header**: Add `-H "Authorization: Bearer <your-admin-jwt-token>"` to your API calls.

**Obtain an Admin JWT Token**:

```bash
curl -X POST https://ids.fabrixly.com/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "admin@example.com",
    "password": "your-admin-password"
  }'

```

*Note: This returns a JSON response containing a `token`.*

```bash
curl -X POST https://ids.fabrixly.com/api/clients \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <your-admin-jwt-token>" \
  -d '{
    "client_name": "Implicit Flow SPA",
    "redirect_uris": ["http://localhost:3009/callback"],
    "response_types": ["id_token", "token"],
    "grant_types": ["implicit"],
    "token_endpoint_auth_method": "none",
    "auth_mode": "flexible"
  }'

```

## Step 2: Example Implicit Flow SPA

Create an HTML file `implicit-spa.html`:

```html
<!DOCTYPE html>
<html>
<head>
  <title>Implicit Flow Demo</title>
  <style>
    .hidden { display: none; }
  </style>
</head>
<body>
  <h1>Implicit Flow Demo</h1>
  
  <div id="login-section">
    <button id="login-btn">Login</button>
  </div>
  
  <div id="user-section" class="hidden">
    <h2>Hello, <span id="user-name"></span></h2>
    <p>Email: <span id="user-email"></span></p>
    <p>Access Token: <span id="access-token"></span></p>
    <button id="logout-btn">Logout</button>
  </div>
  
  <script>
    const ISSUER_URL = 'https://ids.fabrixly.com/oidc';
    const CLIENT_ID = 'your-implicit-client-id';
    const REDIRECT_URI = 'http://localhost:3009/callback';
    const SCOPE = 'openid profile email';
    
    // Helper functions
    function generateRandomString(length) {
      const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
      let result = '';
      for (let i = 0; i < length; i++) {
        result += chars.charAt(Math.floor(Math.random() * chars.length));
      }
      return result;
    }
    
    function parseHash(hash) {
      const params = {};
      const queryString = hash.substring(1);
      const regex = /([^&=]+)=([^&]*)/g;
      let m;
      while (m = regex.exec(queryString)) {
        params[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
      }
      return params;
    }
    
    // Check for tokens in URL hash when page loads
    window.addEventListener('DOMContentLoaded', async () => {
      if (window.location.hash) {
        const params = parseHash(window.location.hash);
        
        if (params.access_token || params.id_token) {
          // Store tokens
          sessionStorage.setItem('access_token', params.access_token);
          sessionStorage.setItem('id_token', params.id_token);
          
          // Clear hash from URL
          window.history.replaceState({}, document.title, window.location.pathname);
          
          // Show user info
          await showUserInfo(params.access_token);
        }
      } else if (sessionStorage.getItem('access_token')) {
        await showUserInfo(sessionStorage.getItem('access_token'));
      } else {
        // Show login button
        document.getElementById('login-section').classList.remove('hidden');
      }
    });
    
    // Login handler
    document.getElementById('login-btn').addEventListener('click', () => {
      const state = generateRandomString(32);
      const nonce = generateRandomString(32);
      sessionStorage.setItem('state', state);
      sessionStorage.setItem('nonce', nonce);
      
      const authUrl = new URL(`${ISSUER_URL}/auth`);
      authUrl.searchParams.set('client_id', CLIENT_ID);
      authUrl.searchParams.set('redirect_uri', REDIRECT_URI);
      authUrl.searchParams.set('response_type', 'id_token token');
      authUrl.searchParams.set('scope', SCOPE);
      authUrl.searchParams.set('state', state);
      authUrl.searchParams.set('nonce', nonce);
      
      window.location.href = authUrl.toString();
    });
    
    // Logout handler
    document.getElementById('logout-btn').addEventListener('click', () => {
      sessionStorage.clear();
      document.getElementById('login-section').classList.remove('hidden');
      document.getElementById('user-section').classList.add('hidden');
    });
    
    // Fetch user info
    async function showUserInfo(accessToken) {
      try {
        const response = await fetch(`${ISSUER_URL}/me`, {
          headers: { 'Authorization': `Bearer ${accessToken}` }
        });
        const user = await response.json();
        
        document.getElementById('user-name').textContent = user.name;
        document.getElementById('user-email').textContent = user.email;
        document.getElementById('access-token').textContent = accessToken.substring(0, 20) + '...';
        
        document.getElementById('login-section').classList.add('hidden');
        document.getElementById('user-section').classList.remove('hidden');
      } catch (err) {
        console.error('Error fetching user info:', err);
      }
    }
  </script>
</body>
</html>

```

## Step 3: Serve the SPA

Run a simple HTTP server to serve `implicit-spa.html`:

```bash
npx http-server -p 3009

```

Visit [http://localhost:3009/implicit-spa.html](http://localhost:3009/implicit-spa.html?ref=blog.fabrixly.com) to test!

## Implicit Flow Steps

1. SPA redirects user to Fabrixly-IDS authorization endpoint
2. User logs in (via any auth mode)
3. Fabrixly-IDS redirects back to SPA with `id_token` and/or `access_token` in URL hash
4. SPA parses tokens from hash
5. SPA stores tokens in sessionStorage or localStorage
6. SPA uses access token to call APIs

## Security Considerations

- **Use HTTPS always**: Tokens are in URL, so HTTPS is critical!
- **Short-lived tokens**: Implicit flow tokens have short expiry
- **Don't store in localStorage**: Prefer sessionStorage to limit token lifetime
- **Validate state and nonce**: Prevents CSRF and replay attacks
- **Prefer Authorization Code Flow with PKCE**: For new apps, use PKCE instead of implicit!

## Troubleshooting

- **Tokens not in URL hash**: Check client's `response_types` includes `id_token` and/or `token`
- **"Invalid redirect\_uri"**: Verify redirect URI matches exactly what's in client config
- **CORS errors**: Ensure your SPA domain is allowed by Fabrixly-IDS CORS settings

## Next Steps

- Try Authorization Code Flow with PKCE instead!
- Add token refresh using silent authentication