Repository navigation
server: read authorize parameters from the POST form body - #205
Open
abhiramshaji-cyber wants to merge 1 commit into
Open
abhiramshaji-cyber wants to merge 1 commit into
abhiramshaji-cyber wants to merge 1 commit into
Conversation
The /authorize endpoint accepts GET and POST, but serveAuthorize only read parameters from r.URL.Query(). A client sending the request as an application/x-www-form-urlencoded POST body, which RFC 6749 section 3.1 allows, got "must specify redirect_uri". Parse the request with r.ParseForm and read parameters from r.Form, so values in the POST body and in the query string are both honored. A request whose form or query cannot be parsed now gets invalid_request. Fixes tailscale#195 Signed-off-by: abhiramshaji-cyber <write4abhiram@gmail.com>
Author
Author
|
Hope you're doing well, @mikeodr! It's me again from my note on 10/28 about the Linux CI run, which is still waiting whenever you have a moment, and I know you've been busy keeping tsidp's Go and Nix bits fresh, so there's truly no rush. If anything else would help, or you'd like the change shaped differently, I'm happy to rework it. I saw #209 just landed for offline_access, so I'm curious whether making tsidp work smoothly with more off the shelf OIDC clients is where the project is heading, and whether there's an area like that where outside help is most useful. Any tips on how you like contributions to tsidp to come in would be really welcome too, thank you! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #195
A sign in request sent as a POST form to
/authorizewas rejected for a missingredirect_uri; now the form values are read the same as query values.What this code is for
serveAuthorizeinserver/authorize.gohandles/authorize, the first step of an OAuth sign in. A relying party sends the user there withclient_id,redirect_uri,state,nonce,scopeand PKCE values. It checks the client and redirect, asksWhoIswho the user is, stores anAuthRequest, and redirects back with acode.Before this PR
A relying party signs a user in by sending
POST /authorizewithclient_idandredirect_uriin anapplication/x-www-form-urlencodedbody.serveAuthorizechecksr.Methodand allowsPOST.uq := r.URL.Query(), which only holds the query string.uq.Get("redirect_uri")returns"".400 invalid_request - must specify redirect_uri.After this PR
Same relying party, same
POST /authorize.serveAuthorizechecksr.Methodand allowsPOST.r.ParseForm()and reads parameters fromr.Form, which holds the body values and the query values.uq.Get("redirect_uri")anduq.Get("client_id")return the values from the body.code.A
GET /authorizewith parameters in the query string goes through the same steps and works as before.The diagram
flowchart LR classDef box fill:#eef1ff,stroke:#4c5bd4,color:#111827 classDef bad fill:#ffd6d6,stroke:#cc0000,color:#111827,stroke-width:3px classDef good fill:#c8f0c8,stroke:#008800,color:#111827,stroke-width:3px subgraph BEFORE["BEFORE: POST form gets 400"] direction TB B1["POST /authorize with form body"] --> B2["serveAuthorize allows POST"] B2 --> B3["uq := r.URL.Query()"] B3 --> B4{"redirect_uri in query?"} B4 -->|"POST body ignored"| B5["400 must specify redirect_uri"] B4 -->|"GET with query"| B6["redirect with code"] end subgraph AFTER["AFTER: POST form gets a code"] direction TB A1["POST /authorize with form body"] --> A2["serveAuthorize allows POST"] A2 --> A3["r.ParseForm()"] A3 --> A4{"THE CHANGE: uq := r.Form"} A4 -->|"POST body read"| A5["redirect with code"] A4 -->|"GET with query"| A6["redirect with code, same as before"] end B1 ~~~ A1 class B1,B2,B3,B6 box class A1,A2,A3,A6 box class B4,B5 bad class A4,A5 good linkStyle 3 stroke:#cc0000,stroke-width:5px linkStyle 8 stroke:#008800,stroke-width:5px style BEFORE fill:#fff5f5,stroke:#cc0000,color:#111827 style AFTER fill:#f3fff3,stroke:#008800,color:#111827The change
In
serveAuthorize,uq := r.URL.Query()becomes a call tor.ParseForm()followed byuq := r.Form. Every lateruq.Get(...)call is unchanged. Whenr.ParseForm()returns an error, the handler returns400 invalid_requestwithfailed to parse form, the same wayserver/ui.gohandles it.server/authorize_test.goaddsusePOSTFormandrawBodytoTestServeAuthorize, with rows for a POST form that issues a code and keepsstateandnonce, a POST form withoutredirect_uri, and a POST body that cannot be parsed.What changes for a user
/authorizeas a POST form now complete sign in.GET /authorizewith a query string works as before.uq.Getreturns the body value, becauser.Formlists body values first.%escape, now gets400 invalid_requestinstead of having the bad pair dropped. Taken on purpose, so a malformed request is reported instead of half read.