Class: StandardId::Oauth::AuthorizationCodeFlow
- Inherits:
-
TokenGrantFlow
- Object
- BaseRequestFlow
- TokenGrantFlow
- StandardId::Oauth::AuthorizationCodeFlow
- Defined in:
- lib/standard_id/oauth/authorization_code_flow.rb
Instance Attribute Summary
Attributes inherited from TokenGrantFlow
Attributes inherited from BaseRequestFlow
#current_account, #params, #request
Instance Method Summary collapse
Methods inherited from TokenGrantFlow
#execute, extra_permitted_keys, #initialize
Methods inherited from BaseRequestFlow
expect_params, expected_params, extra_permitted_keys, #initialize, permit_params, permitted_params
Constructor Details
This class inherits a constructor from StandardId::Oauth::TokenGrantFlow
Instance Method Details
#authenticate! ⇒ Object
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
# File 'lib/standard_id/oauth/authorization_code_flow.rb', line 7 def authenticate! @client = StandardId::ClientApplication.find_by(client_id: params[:client_id]) raise StandardId::InvalidClientError, "Client authentication failed" if @client.nil? # Confidential clients authenticate with a client secret. Public clients # (e.g. native/SPA/MCP clients per RFC 8252 / OAuth 2.1) cannot keep a # secret and authenticate via PKCE alone — they MUST NOT send one. if @client.confidential? @credential = validate_client_secret!(params[:client_id], params[:client_secret]) elsif params[:client_secret].present? raise StandardId::InvalidClientError, "Public clients must not send a client_secret" end @authorization_code = (params[:code]) unless @authorization_code&.valid_for_client?(params[:client_id]) raise StandardId::InvalidGrantError, "Invalid or expired authorization code" end if params[:redirect_uri].present? && @authorization_code.redirect_uri != params[:redirect_uri] raise StandardId::InvalidGrantError, "Redirect URI mismatch" end # Fail closed: a public client's only authentication factor is PKCE, so a # code minted without a code_challenge offers no client authentication at # all. (pkce_valid? returns true when code_challenge is blank, which is # safe for confidential clients but would be a bypass for public ones.) if @client.public? && @authorization_code.code_challenge.blank? raise StandardId::InvalidGrantError, "PKCE is required for public clients" end unless @authorization_code.pkce_valid?(params[:code_verifier]) raise StandardId::InvalidGrantError, "Invalid PKCE code_verifier" end @authorization_code.mark_as_used! emit_code_consumed end |