Endpoints
Every Gigadrive IDP endpoint, its parameters, its errors, and the token lifetimes it produces.
Access is granted per request
These endpoints only answer for a client Gigadrive created for you. There is no dynamic registration endpoint. See Requesting access.
The issuer is https://idp.gigadrive.de. Every endpoint in this reference uses that origin.
| Endpoint | Method | Specification |
|---|---|---|
/.well-known/openid-configuration | GET | OpenID Connect Discovery |
/.well-known/jwks.json | GET | RFC 7517 |
/oauth2/authorize | GET | RFC 6749 §4.1, plus PKCE |
/oauth2/token | POST | RFC 6749, RFC 8628 |
/oauth2/userinfo | GET | OpenID Connect Core §5.3 |
/oauth2/revoke | POST | RFC 7009 |
/oauth2/device_authorization | POST | RFC 8628 §3.1 and §3.2 |
Discovery and keys
Fetch /.well-known/openid-configuration and configure your library from it rather than hard-coding paths. It reports the issuer, the JWKS URI, the supported scopes and grants, subject_types_supported: ["public"], id_token_signing_alg_values_supported: ["RS256"], and code_challenge_methods_supported: ["S256"].
Both documents are served with Cache-Control: public, max-age=300, stale-while-revalidate=600.
Signing keys rotate twice a year, at 00:00 UTC on 1 January and 1 July.
Select the verification key by the JWT's kid header. Pinning one key means your integration breaks on a rotation day.
Authorize
GET /oauth2/authorize starts a sign-in. Only response_type=code is accepted; anything else is a 400 with invalid_client and "Unsupported response_type".
| Parameter | Required | Rules |
|---|---|---|
client_id | Yes | Your client UUID |
redirect_uri | Yes | Must match a registered URI |
response_type | Yes | code |
scope | Yes | Space-separated, every value from the catalogue |
state | Yes | Required by Gigadrive, not merely recommended. Echoed back |
code_challenge | For public clients | The S256 challenge |
code_challenge_method | For public clients | S256. plain is refused for every client type |
nonce | No | Up to 512 characters, echoed into the ID token |
Errors split by whether the redirect URI can be trusted. A bad client_id or redirect_uri returns JSON with 400, because sending a user to an unvalidated URI would make the endpoint an open redirector. An invalid scope, a PKCE failure, or a denied request redirects back to your client with error and state in the query string. A request whose session Gigadrive cannot verify right now returns 503 temporarily_unavailable, deliberately rather than bouncing a signed-in user to the login screen.
Without a session the user is redirected to Gigadrive sign-in with a returnTo pointing at your original authorize URL, so the flow resumes by itself once they sign in.
Authorization codes live 10 minutes and are single-use. Consumption is atomic, so two racing exchanges of the same code cannot both succeed.
Token
POST /oauth2/token, always Cache-Control: no-store. Authenticate the client with HTTP Basic, or with client_id and client_secret in the body. Basic wins when both are present.
Three grants are accepted: authorization_code, refresh_token, and urn:ietf:params:oauth:grant-type:device_code.
A success is 200 with token_type, access_token, expires_in, and, depending on the grant and scopes, scope, refresh_token, and id_token.
| Token | Lifetime | Issued when |
|---|---|---|
| Access token | 300 seconds | Always |
| ID token | 300 seconds | The openid scope was granted |
| Refresh token | 30 days | The offline_access scope was granted |
The refresh grant rotates: each use returns a new refresh token and retires the one you sent. Store the new value before you use the access token.
Redemption re-checks the world rather than trusting the moment of approval. A suspended account, a client sign-in policy that no longer permits the user, and product access that has since been withdrawn all turn a valid code into 400 invalid_request with access_denied.
Client authentication failures are 401 invalid_client. Everything else is 400, including the device-flow poll responses authorization_pending, slow_down, access_denied, and expired_token.
UserInfo
GET /oauth2/userinfo with Authorization: Bearer <access_token>. The openid scope is required, and a token without it gets 403 { "error": "insufficient_scope" }.
A missing, malformed, or expired token gets 401 { "error": "invalid_token" } plus a WWW-Authenticate: Bearer header. So does a token whose subject no longer exists, deliberately, because a 200 with empty claims is something a relying party will mistake for a signed-in user.
Which claims come back depends on the scopes. See Scopes and claims.
Revoke
POST /oauth2/revoke with token, an optional token_type_hint, and your client credentials in the body. Client authentication is required; without it you get 401 invalid_client.
For an authenticated client the answer is always 200, whether or not the token existed. That is RFC 7009 behavior, and it stops the endpoint from becoming a token oracle.
Only refresh tokens are revocable, and only ones belonging to the authenticated client. Access tokens are self-contained JWTs with no revocation list; they stop working when they expire, within five minutes.
Device authorization
POST /oauth2/device_authorization with client_id and scope. No redirect URI, no PKCE: the entropy of the device code plus the user approving it in a browser is the boundary. This is how gigadrive login signs you in.
Starting a device flow is rate limited to 30 requests per minute for each pair of client and source address.
In the following request, replace the client id with the one Gigadrive issued you.
curl -X POST https://idp.gigadrive.de/oauth2/device_authorization \
-H 'Content-Type: application/json' \
-d '{"client_id":"3f1c9a72-5d84-4a1e-9c31-8b6f0d4e7a52","scope":"openid profile email offline_access"}'The response carries device_code, user_code, verification_uri, verification_uri_complete, expires_in of 600 seconds, and interval of 5 seconds.
verification_uri is https://account.gigadrive.de/device, and verification_uri_complete is the same URL with the code already in the query string. The user_code is formatted XXXX-XXXX from a Crockford base32 alphabet with I, L, O, and U removed, so nobody has to guess whether they are reading a one or an el. Render the complete URI as a link where you can, and read out the short one plus the code where you cannot.
Then poll the token endpoint with the device_code grant, honoring interval and backing off further on slow_down.
