Let users sign in with OAuth

Recipes for specific tasks against the API.

Use OAuth when other people sign in to your app with their MangaBaka account.

For scripts acting as yourself, a personal access token is simpler.

MangaBaka is a standard OAuth 2.0 / OpenID Connect provider using the authorization code flow with PKCE. Everything below is also published in the discovery document.

1. Register your app#↑

Open New application (any signed-in account can create one) and fill in:

  • Type: Web for a server that can keep a secret. Native App or Other for mobile, desktop and single-page apps, which can't.
  • Public application: on for Native and Other. A public client has no secret and must use PKCE.
  • Redirect URL: where users land after signing in. It must match the redirect_uri you send exactly.

Save, then copy the client id and, for a Web app, the client secret. The secret is shown only once.

2. Send the user to sign in#↑

Generate a random state and a PKCE code_verifier, then redirect the user to this URL. It is split over lines for reading; join it into one line and URL-encode each value (the spaces in scope become %20):

https://mangabaka.org/auth/oauth2/authorize
  ?response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=https://your.app/callback
  &scope=openid profile library.read offline_access
  &state=RANDOM_STATE
  &code_challenge=BASE64URL_SHA256_OF_VERIFIER
  &code_challenge_method=S256

Only S256 is supported as the challenge method. Always include openid: the API rejects tokens without it. Beyond that, ask for the fewest scopes you need: OAuth scopes lists what each one grants and which endpoints accept it.

The user signs in, reviews the scopes you asked for, and approves.

3. Handle the callback#↑

MangaBaka redirects to your redirect_uri with code and state in the query. Reject the request if state doesn't match the one you generated.

4. Exchange the code for tokens#↑

curl -X POST "https://mangabaka.org/auth/oauth2/token" \
  -d grant_type=authorization_code \
  -d code=THE_CODE \
  -d redirect_uri=https://your.app/callback \
  -d client_id=YOUR_CLIENT_ID \
  -d code_verifier=YOUR_CODE_VERIFIER

A Web app also authenticates with its secret, either as client_secret in the body or with HTTP Basic auth.

The response:

{
	"access_token": "ACCESS_TOKEN",
	"token_type": "Bearer",
	"expires_in": 604800,
	"expires_at": 1793717497,
	"refresh_token": "REFRESH_TOKEN",
	"scope": "openid profile offline_access library.read",
	"id_token": "ID_TOKEN"
}

refresh_token is only there if you asked for offline_access, and id_token only with openid. A failure answers in the standard OAuth shape, { "error": "...", "error_description": "..." }, not the API's error body. A wrong code_verifier is 401 with invalid_request.

Store the user's id now: call the userinfo endpoint and keep its sub.

5. Call the API#↑

Send the access token as a bearer token:

curl -H "Authorization: Bearer ACCESS_TOKEN" \
  "https://api.mangabaka.org/v2/my/library"

An invalid or expired token returns 401. A valid token without the endpoint's scope returns 403.

6. Refresh and revoke#↑

Before the access token expires, trade the refresh token for a new one:

curl -X POST "https://mangabaka.org/auth/oauth2/token" \
  -d grant_type=refresh_token \
  -d refresh_token=REFRESH_TOKEN \
  -d client_id=YOUR_CLIENT_ID

A Web app sends its secret here too, the same way as in step 4.

Each refresh returns a new refresh token and retires the old one. Store the new one right away: sending a retired refresh token again revokes every token your app holds for that user, and they have to sign in again.

  • Refresh once per user at a time. There is no grace window: of two concurrent refreshes with the same token, one gets 400 invalid_grant, and retrying it with that token revokes everything.
  • invalid_grant on refresh means the token is gone: send the user through sign-in again.

When a user disconnects your app, revoke their refresh token:

curl -X POST "https://mangabaka.org/auth/oauth2/revoke" \
  -d token=REFRESH_TOKEN \
  -d token_type_hint=refresh_token \
  -d client_id=YOUR_CLIENT_ID

Users can also revoke access themselves under API and apps.

Native and single-page apps#↑

The flow is the same. What changes:

  • No secret. Register as Native App or Other with Public application on. Never ship a client secret inside an app; anyone can extract it. PKCE replaces it.
  • Redirect URL. Register a custom scheme your app handles (com.example.app:/callback) or a loopback address (http://127.0.0.1/callback). For 127.0.0.1 any port matches, so the app can listen on whichever port is free.
  • Token storage. Keep tokens in the platform's secure storage (Keychain, Android Keystore), not in plain files or localStorage.