Direct OAuth2 Authentication with PocketID and Traefik OIDC Plugin

This guide demonstrates how to implement seamless OAuth2 authentication for your Pangolin resources using PocketID and the Traefik OIDC plugin. Unlike traditional setups that require users to navigate through multiple login pages, this approach redirects users directly to PocketID’s login page where they can authenticate with passkeys.

:sparkles: Why This Matters

Traditional authentication flows often require users to:

  1. Visit your application
  2. Get redirected to Pangolin’s login page
  3. Click to authenticate with a third-party provider
  4. Complete authentication and return to your app

With this direct OAuth2 implementation:

  1. Users visit your protected resource
  2. They’re immediately redirected to PocketID
  3. They authenticate with passkeys
  4. They’re returned directly to your application

This streamlined experience feels more professional and reduces friction for your users.

:clipboard: Prerequisites

  • Pangolin with Middleware Manager installed
  • A domain with DNS properly configured
  • Basic understanding of OAuth2/OIDC concepts

:rocket: Step 1: Set Up PocketID Authentication Server

First, you’ll need a running PocketID instance. You can follow our guide on Using AWS CloudFormation to Create Test Authentication Servers to quickly deploy PocketID.

Alternatively, you can add the following to your docker compose to run pocketid on your VPS

    pocketid:
      image: ghcr.io/pocket-id/pocket-id
      container_name: pocketid
      restart: unless-stopped
      env_file: .env
      volumes:
        - "./pocketid:/app/backend/data"

and include the following in your dynamic_config.yml file

    # Add these lines for pocketid
    # pocketid http redirect router
    pocketid-router-redirect:
      rule: "Host(`pocketid.yourdomain.com`)"
      service: pocketid-service
      entryPoints:
        - web
      middlewares:
        - redirect-to-https

    # pocketid router
    pocketid:
      rule: "Host(`pocketid.yourdomain.com`)"
      service: pocketid-service
      entryPoints:
        - websecure
      tls:
        certResolver: letsencrypt

    pocketid-service:
      loadBalancer:
        servers:
          - url: "http://pocketid:1411"

Once deployed, your PocketID instance should be accessible at https://pocketid.yourdomain.com.

:bust_in_silhouette: Step 2: Configure PocketID Admin Account

When accessing PocketID for the first time, you’ll need to set up an admin account:

  1. Navigate to https://pocketid.yourdomain.com/setup
  2. Follow the prompts to create your administrator account
  3. Register a passkey for secure authentication

:key: Step 3: Create an OIDC Client in PocketID

Now you’ll create an OAuth2/OIDC client that your applications will use:

  1. Log in to PocketID admin interface
  2. Navigate to the Clients section
  3. Create a new client with these settings:
    • Name: MyAuth (or any descriptive name)
    • Callback URL: https://*.yourdomain.com/oidc/callback (wildcard allows any subdomain)
  4. Save the client configuration
  5. Important: Copy the generated Client ID and Client Secret - you’ll need these later

:electric_plug: Step 4: Add the OIDC Plugin to Traefik

Edit your config/traefik/traefik_config.yml file to include the OIDC authentication plugin:

experimental:
  plugins:
    traefik-oidc-auth:
      moduleName: "github.com/sevensolutions/traefik-oidc-auth"
      version: "v0.11.0"

:gear: Step 5: Create the OIDC Middleware

  1. Open the Pangolin Middleware Manager
  2. Navigate to the Middlewares tab
  3. Click Create Middleware
  4. Select Plugin as the middleware type
  5. Name it “Traefik OIDC Auth” (or similar)
  6. Enter the following JSON configuration, replacing the placeholder values with your actual Client ID, Client Secret, and PocketID domain:
{
  "traefik-oidc-auth": {
    "Provider": {
      "ClientId": "ee55e81a-e06f-408a-92cf-5f7dd55a1a70",
      "ClientSecret": "YourClientSecret",
      "TokenValidation": "IdToken",
      "Url": "https://pocketid.yourdomain.com"
    },
    "Scopes": [
      "openid",
      "profile",
      "email"
    ]
  }
}
  1. Click Update Middleware

:shield: Step 6: Protect Your Resources

  1. From the Middleware Manager dashboard, select the resource you want to protect
  2. Click Manage
  3. Under Attached Middlewares, click Add Middleware
  4. Select your newly created OIDC middleware
  5. Click Add Middlewares
  6. Save your changes

:test_tube: Step 7: Test the Authentication Flow

  1. Open an incognito/private browser window
  2. Navigate to your protected resource (e.g., https://app.yourdomain.com)
  3. You should be immediately redirected to the PocketID login page
  4. Authenticate using your passkey

:magnifying_glass_tilted_left: Step 8: Consent Screen (First-time Access)

The first time you access a protected resource, PocketID will display a consent screen asking permission to share your information with the application.

  1. Review the requested permissions
  2. Click Allow to proceed

After granting consent, you’ll be redirected to your protected resource, now authenticated!

:counterclockwise_arrows_button: Troubleshooting

Issue: Not being redirected to PocketID when accessing a protected resource after clearing cookies.

Solution: Browser caching can sometimes interfere with the authentication flow. Try:

  1. Open Developer Tools (F12 or Right-click > Inspect)
  2. Navigate to Application > Storage
  3. Click “Clear site data” to completely remove all stored data for the site
  4. Reload the page

:pushpin: Summary

This direct OAuth2 authentication approach with PocketID and the Traefik OIDC plugin offers:

  • A streamlined, professional user experience
  • Secure passkey authentication
  • No intermediate login pages
  • Simplified user journey

By implementing this solution, you’re providing your users with a modern, frictionless authentication experience while maintaining robust security standards.

:folded_hands: Thanks for Reading

We hope this guide helps you implement a smoother authentication flow for your Pangolin resources. If you have questions or need further assistance, please visit our community forum.

3 Likes

Thanks for the tutorial, very easy to follow.

Question, is this one of those implementations where if you for example can’t reach PocketID or PocketID is currently down then you cannot login to the resources? Or can you setup a fallback login?

I recall for example Portainer shows both the oAuth and internal authentication methods in case the first one is down or something.

Thanks

That’s a good question. There isn’t a fall back for now as far as I know but in the case of a failure I recommend using the middleware manager to remove the middleware from the resource and you can login

1 Like

For those without AWS accounts (there are such people for sure) is it possible to install PocketID container on same machine as Pangolin is running? Same way that Tinyauth was integrated in " Implementing External Authentication in Pangolin Using Tinyauth and the Middleware Manager" ?

Try including pocketid in your docker compose and then follow the rest of the instructions in the Aws guide

pocketid:
              image: ghcr.io/pocket-id/pocket-id
              container_name: pocket-id
              restart: unless-stopped
              env_file: .env
              volumes:
                - "./pocketid:/app/backend/data"
              labels:
                - "traefik.enable=true"
                - "traefik.http.routers.pocket-id.entrypoints=websecure"
                - "traefik.http.routers.pocket-id.rule=Host(`auth.yourdomain.com`)"
                - "traefik.http.routers.pocket-id.tls=true"
                - "traefik.http.routers.pocket-id.tls.certresolver=myresolver"
                - "traefik.http.routers.pocket-id.service=pocket-id"
                - "traefik.http.services.pocket-id.loadbalancer.server.port=80"
                - "traefik.http.routers.pocket-id.middlewares=redirect-to-https"
                - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"          
          

Thanks a million Ivo.

I tired to create pocket-id container with provided config. I have changed domain name, certresolver, as in my case it’s letsencrypt and placed fqdn in env file: PUBLIC_APP_URL=https://. I’ve also modified volumes to “./config/pocketid:/app/backend/data” and created pocketid folder under config. Entire stack started normally (pocket-id container is up), no errors after running “docker logs pocket-id”. Unfortunately I cannot access the pocket id public url - 404 page not found. I have checked Traefik dashboard but no entries about pocket-id. Any thoughts?

You might not have port 80 exposed in traefik. Try just this in your docker compose and then add more services as you get it working

          services:
            traefik:
              image: traefik:v3.4.0
              container_name: traefik
              restart: unless-stopped
              ports:
                - "80:80"
                - "443:443"
              command:
                - "--api.insecure=false"
                - "--providers.docker=true"
                - "--providers.docker.exposedbydefault=false"
                - "--entrypoints.web.address=:80"
                - "--entrypoints.websecure.address=:443"
                - "--certificatesresolvers.myresolver.acme.httpchallenge=true"
                - "--certificatesresolvers.myresolver.acme.httpchallenge.entrypoint=web"
                - "--certificatesresolvers.myresolver.acme.email=admin@yourdomain.com"
                - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
              volumes:
                - /var/run/docker.sock:/var/run/docker.sock:ro
                - ./traefik/letsencrypt:/letsencrypt

            pocketid:
              image: ghcr.io/pocket-id/pocket-id
              container_name: pocket-id
              restart: unless-stopped
              env_file: .env
              volumes:
                - "./pocketid:/app/backend/data"
              labels:
                - "traefik.enable=true"
                - "traefik.http.routers.pocket-id.entrypoints=websecure"
                - "traefik.http.routers.pocket-id.rule=Host(`auth.yourdomain.com`)"
                - "traefik.http.routers.pocket-id.tls=true"
                - "traefik.http.routers.pocket-id.tls.certresolver=myresolver"
                - "traefik.http.routers.pocket-id.service=pocket-id"
                - "traefik.http.services.pocket-id.loadbalancer.server.port=80"
                - "traefik.http.routers.pocket-id.middlewares=redirect-to-https"
                - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"      

Thanks and sorry for being a pain.
The vanilla config you provided does not work for me out of the box. I had to change the fallowing line changing port from 80 to 1411 (default pocket ID port that is being assigned to container).
- "traefik.http.services.pocket-id.loadbalancer.server.port=1411"
Once applied change, I did get PocketID login page
Even then, during PocketID initial setup, when I tried to create new passkey on fresh PocketID account I got “An unknown error occurred. Please try again.”
It also looks like PocketID initial URL has been changed from https://pocketid.yourdomain.com/login/setup to https://pocketid.yourdomain.com/setup
Not sure why I cannot set new passkey on fresh deployment. Any thoughts?

Maybe things have changed on pocketid side since I wrote the guide. I will be setting up pocketid myself tomorrow so I will let you know

I was able to fix the issue. It was misconfiguration in my .env file. Also config path has been changed on pocketid container. It is now pointing to /app/data instead /app/backend/data. I’m now able to login and set my passkey in pocketID. Thanks

1 Like

Is there any way to make the plugin bypass if you are on local network 192.168.0.0 ?

Configure a different resource in pangolin that doesn’t use oauth and lock that down to an IP address range

So to a different dns name? Or can it be the same?

Nvm, I solved it from the help here:

As stated on the github issues, traefik needs to be restarted for the condition to start working.

{
  "traefik-oidc-auth": {
    "BypassAuthenticationRule": "HeaderRegexp(`X-Real-Ip`, `(^|,\\s*)192\\.168\\.(1|67)\\.[0-9]{1,3}($|,)`)",,
    "Provider": {
      "ClientId": "redacted",
      "ClientSecret": "redacted",
      "TokenValidation": "IdToken",
      "Url": "https://id.redacted.com"
    },
    "Scopes": [
      "openid",
      "profile",
      "email"
    ],
    "Secret": "redacted"
  }
}

Cool. I didn’t know you could do that. Great find. Thanks for sharing

1 Like