Skip to content

fix: make it run (PPT-2536)#1

Draft
chillfox wants to merge 7 commits into
masterfrom
PPT-2536-replace-ruby-auth-with-auth-cr
Draft

fix: make it run (PPT-2536)#1
chillfox wants to merge 7 commits into
masterfrom
PPT-2536-replace-ruby-auth-with-auth-cr

Conversation

@chillfox

@chillfox chillfox commented Jul 9, 2026

Copy link
Copy Markdown

No description provided.

chillfox added 7 commits July 7, 2026 16:53
The authorization_code grant relied on Authly's default
grant_strategy.user_id (nil), so issued tokens carried a random sub.
As a result the ClaimsProvider could not resolve the user and omitted
the aud claim and the legacy u{n,e,p,r} metadata block.

Recover the user_id captured in the authorization code (matching the
legacy Ruby Doorkeeper::JWT token, whose sub is the user id) so sub,
aud, and u are populated for downstream PlaceOS services.

Adds spec/controllers/oauth_token_claims_spec.cr covering the code flow.
Authly builds the scope claim as a space-separated string, but the
legacy Ruby service emitted scope: Array(opts[:scopes]) and downstream
PlaceOS services decode it into UserJWT#scope : Array(Scope). A string
scope makes UserJWT.decode raise. Split the scope string into an array
in the ClaimsProvider so issued tokens are decodable by consumers.
Authly adds a cid (client id) claim that the legacy Ruby Doorkeeper
token never carried. Delete it in the ClaimsProvider so the emitted
claim set matches the legacy token shape. The persisted OAuthToken
record still records the client id via the token-store metadata, which
is populated independently of the JWT payload.
The legacy Ruby service mounts its Doorkeeper OAuth server endpoints
under /auth/oauth/* (token, authorize, revoke, userinfo), and that path
family is the documented public contract for server-to-server and
native app clients (auth/README.md, auth/docs/sample_auth.md). auth.cr
serves them at /auth/*. Add /auth/oauth/* route aliases on the existing
actions so clients that hardcode the Doorkeeper paths keep working after
the swap. The OIDC discovery document continues to advertise the /auth/*
paths for discovery-driven clients.
The legacy Ruby service accepts browser login forms posted as
application/x-www-form-urlencoded, but action-controller only registers
a JSON body parser by default, so POST /auth/signin returned 415 for
form posts. SigninBody already defined .from_form; wire it up by
registering a form-urlencoded body parser on the Application base
controller so form logins are accepted (202 + Set-Cookie), matching the
legacy behaviour.
The legacy Ruby logout redirects via redirect_continue(continue || "/"),
issuing a 302 to the continue target when safe, to "/" when no continue
is given, and to the authority logout_url only as the cross-domain
fallback. auth.cr issued a 303 and defaulted to the authority logout_url
even with no continue. Align the target selection and use 302 so logout
behaves as a drop-in for existing clients.
Authly's AccessToken#expires_in derives from an ACCESS_TTL constant
captured at class-load time, before configure! applies the 2-hour access
TTL, so the token response reported the authly default of 3600s while
the JWT exp claim was a full 7200s. Report the live configured TTL so
the RFC 6749 expires_in matches both the JWT exp and the legacy 2-hour
Ruby service.
@chillfox chillfox self-assigned this Jul 9, 2026
@chillfox chillfox changed the title Ppt 2536 replace ruby auth with auth cr Ppt 2536 replace ruby auth with auth.cr (PPT-2536) Jul 9, 2026
@chillfox chillfox changed the title Ppt 2536 replace ruby auth with auth.cr (PPT-2536) fix: make it run (PPT-2536) Jul 9, 2026
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.

1 participant