RFC Compliance
When implementing or modifying OAuth protocol behavior in Doorkeeper, use this skill to verify the implementation stays aligned with the relevant RFCs.
Core RFCs
| RFC | Topic | Key Files |
|---|---|---|
| 6749 | OAuth 2.0 Framework | lib/doorkeeper/oauth/, app/controllers/doorkeeper/ |
| 6750 | Bearer Token Usage | lib/doorkeeper/oauth/token.rb, lib/doorkeeper/rails/helpers.rb |
| 7009 | Token Revocation | app/controllers/doorkeeper/tokens_controller.rb (revoke action) |
| 7636 | PKCE | lib/doorkeeper/oauth/pre_authorization.rb, lib/doorkeeper/oauth/authorization_code_request.rb |
| 7662 | Token Introspection | lib/doorkeeper/oauth/token_introspection.rb |
| 8252 | OAuth for Native Apps | lib/doorkeeper/oauth/helpers/uri_checker.rb (loopback) |
| 9207 | Authorization Server Issuer Identification | lib/doorkeeper/oauth/code_response.rb (iss param) |
| 8707 | Resource Indicators | lib/doorkeeper/oauth/resource_indicator_validator.rb |
Error Response Format (RFC 6749 §5.2)
Token endpoint errors MUST include:
error— single ASCII error code (required)error_description— human-readable description (optional)- HTTP status codes: 400 for most errors, 401 for invalid client auth
Valid error codes for the token endpoint:
invalid_request, invalid_client, invalid_grant, unauthorized_client, unsupported_grant_type, invalid_scope
Reference: lib/doorkeeper/oauth/error_response.rb
Authorization endpoint errors that are redirectable include error, error_description, and state in the redirect. Non-redirectable errors (invalid redirect_uri, invalid client_id) MUST NOT redirect — render an error page instead.
Reference: lib/doorkeeper/oauth/pre_authorization.rb — redirectable? logic
Token Response Format (RFC 6749 §5.1)
Successful token responses MUST include:
access_token— the token valuetoken_type— "Bearer" (case-insensitive per RFC 6750)expires_in— lifetime in seconds (recommended)
MAY include:
refresh_tokenscope— if different from requested
MUST NOT include:
refresh_tokenin implicit grant responses
Reference: lib/doorkeeper/oauth/token_response.rb
Authorization Code Flow (RFC 6749 §4.1)
- Authorization request →
PreAuthorizationvalidates,Codeissues grant - Token request →
AuthorizationCodeRequestvalidates grant + issues token
Key constraints:
- Code is single-use (§4.1.2) — revoke tokens on replay
- Code must be bound to client_id and redirect_uri
- Code SHOULD expire in max 10 minutes (configurable via
authorization_code_expires_in) - redirect_uri in token request must match the one used in authorization request
PKCE (RFC 7636)
code_challenge_methoddefaults to "plain" when omitted (§4.2) — but Doorkeeper intentionally requires it whencode_challengeis present (secure-by-default deviation)- S256:
BASE64URL(SHA256(code_verifier))must equalcode_challenge - plain:
code_verifiermust equalcode_challenge code_verifieris 43-128 characters from[A-Z] / [a-z] / [0-9] / "-" / "." / "_" / "~"
Token Introspection (RFC 7662)
- MUST require authentication of the requesting party
- Response for inactive/invalid tokens:
{"active": false}— no other fields - Response for active tokens includes:
active,scope,client_id,token_type,exp,iat,sub,aud,iss - Doorkeeper omits
token_typeandexpfor refresh tokens in introspection responses (these fields are OPTIONAL per §2.2, not prohibited — but they are semantically inapplicable to refresh tokens)
Reference: lib/doorkeeper/oauth/token_introspection.rb
Token Revocation (RFC 7009)
- Return 200 OK even for invalid/unknown tokens (§2.1) — prevents token enumeration
- Client authentication is required
- The
token_type_hintparameter is optional; server must still check both types - Revoking an access token SHOULD revoke associated refresh token (and vice versa)
Current known deviation: Doorkeeper returns 403 when the token belongs to a different client, rather than 200.
Bearer Token Errors (RFC 6750 §3)
- 401 responses MUST include
WWW-Authenticate: Bearerheader - Error codes in WWW-Authenticate:
invalid_request,invalid_token,insufficient_scope - 403 for
insufficient_scope, 401 forinvalid_token, 400 forinvalid_request
Reference: lib/doorkeeper/oauth/error_response.rb — authenticate_info method
Resource Indicators (RFC 8707)
- Resource URIs must be absolute and must not contain a fragment
- Multiple resources use repeated
resourceparameters (Rack limitation: useresource[]syntax) - Tokens are audience-restricted to the declared resources
- Refresh requests enforce subset restriction against original grant
Reference: lib/doorkeeper/oauth/resource_indicator_validator.rb
Authorization Server Metadata (RFC 8414)
Served at /.well-known/oauth-authorization-server. Must include:
issuer— MUST be identical to theissin authorization responsesauthorization_endpoint,token_endpointresponse_types_supported,grant_types_supportedtoken_endpoint_auth_methods_supportedscopes_supported(recommended)
Reference: lib/doorkeeper/oauth/metadata_response.rb
Implementation Patterns
Adding a new grant type
- Create a strategy class in
lib/doorkeeper/request/extendingDoorkeeper::Request::Strategy - Create a request class in
lib/doorkeeper/oauth/extendingDoorkeeper::OAuth::BaseRequest - Register with
Doorkeeper::GrantFlow.registerinlib/doorkeeper/grant_flow.rb - Add to default
grant_flowsif it's a standard flow - Add specs in
spec/requests/flows/andspec/lib/oauth/
Adding a new error code
- Add to
lib/doorkeeper/errors.rbas a new class inheritingBaseResponseError - Add I18n key in
config/locales/en.yml - Map to correct HTTP status in the error class's
#typemethod
Adding a new configuration option
- Add via
optionDSL inlib/doorkeeper/config.rb - Add validation in
lib/doorkeeper/config/validations.rbif needed - Document in the initializer template:
lib/generators/doorkeeper/templates/initializer.rb - Add specs in
spec/lib/config_spec.rb
Verification
After implementing protocol changes:
- Run flow specs:
bundle exec rspec spec/requests/flows/ - Run endpoint specs:
bundle exec rspec spec/requests/endpoints/ - Run OAuth unit specs:
bundle exec rspec spec/lib/oauth/ - Verify metadata response:
bundle exec rspec spec/requests/endpoints/metadata_spec.rb