Skip to content

Add OPDS 2 Authorization Code flow with PKCE - #3901

Open
panaC wants to merge 7 commits into
developfrom
feat/opds-pkce
Open

panaC wants to merge 7 commits into
developfrom
feat/opds-pkce

Conversation

@panaC

@panaC panaC commented Sep 21, 2026

Copy link
Copy Markdown
Member

Fixes #3898

@panaC panaC self-assigned this Sep 21, 2026
Comment thread projects/opds-pkce-test-server/server.mjs Fixed
Comment thread projects/opds-pkce-test-server/server.mjs Fixed
@panaC

panaC commented Sep 22, 2026 •

Copy link
Copy Markdown
Member Author
flowchart TD
    A[Thorium requests protected OPDS catalog] --> B{Catalog response}

    B -->|200| Z[Display catalog]
    B -->|401| C[Read OPDS Authentication Document]

    C --> D{PKCE flow type found?}
    D -->|No| X[Try another supported authentication flow]
    D -->|Yes| E[Extract authenticate and refresh links]

    E --> F{Endpoints permitted?}
    F -->|Production: not HTTPS| FAIL[Cancel authentication]
    F -->|Dev/CI: non-loopback HTTP| FAIL
    F -->|Valid| G[Generate random code_verifier and state]

    G --> H[Derive S256 code_challenge]
    H --> I[Open authenticate link in system browser]

    I --> J["Authorization request<br/>response_type=code<br/>shared client_id<br/>redirect_uri=opds://authorize/<br/>code_challenge + S256<br/>state"]

    J --> K{User authorizes?}

    K -->|No| L["Callback<br/>error=access_denied + state"]
    L --> M{State matches?}
    M -->|No| FAIL
    M -->|Yes| FAIL

    K -->|Yes| N["Callback<br/>code + state"]
    N --> O{Transaction valid?}

    O -->|Expired or state mismatch| FAIL
    O -->|Valid| P["POST to refresh link<br/>(OAuth token endpoint)"]

    P --> Q["grant_type=authorization_code<br/>code<br/>redirect_uri<br/>shared client_id<br/>code_verifier"]

    Q --> R{Successful 2xx response?}
    R -->|No| FAIL
    R -->|Yes| S[Store access token and optional refresh token]

    S --> T[Retry catalog with Bearer access token]
    T --> Z

    Z --> U{Later request returns 401?}
    U -->|No| Z
    U -->|No refresh token| C
    U -->|Refresh token available| V["POST to the same refresh link<br/>grant_type=refresh_token<br/>refresh_token<br/>shared client_id"]

    V --> W{Refresh succeeds?}
    W -->|Yes| Y[Store new access token]
    Y --> T
    W -->|No| C
Loading

@panaC
panaC marked this pull request as ready for review September 24, 2026 15:31
@panaC
panaC requested a review from a team as a code owner September 24, 2026 15:31
"X-Content-Type-Options": "nosniff",
"X-Frame-Options": "DENY",
});
response.end(body);
}

function getBearerToken(request) {
return /^Bearer\s+(.+)$/i.exec(request.headers.authorization || "")?.[1];

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

support OAuth 2.0 Authorization Code Flow with PKCE

2 participants