Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refresh token request rejected by auth server with PKCE flow due to missing client_id in refresh request #33

Open
j-krose opened this issue Jul 9, 2024 · 1 comment

Comments

@j-krose
Copy link

j-krose commented Jul 9, 2024

Using PCKE OAuth flow (i.e. no client secret available) to create a client-only web page I ran into the following issue; rather than being able to do an expected:

    Refresh.makeTokenRequest
        (resultMapper >> toMsg)
        { credentials = Nothing
        , url = tokenUrl
        , scope = scopes
        , token = accessToken.refreshToken
        }
        |> Http.request

or

    Refresh.makeTokenRequest
        (resultMapper >> toMsg)
        { credentials = Just { clientId = clientId, secret = "" }
        , url = tokenUrl
        , scope = scopes
        , token = accessToken.refreshToken
        }
        |> Http.request

I had to use the more custom makeTokenRequestWith in order to form the proper request:

    Refresh.makeTokenRequestWith
        OAuth.RefreshToken
        Refresh.defaultAuthenticationSuccessDecoder
        (Dict.singleton "client_id" clientId)
        (resultMapper >> toMsg)
        { credentials = Nothing
        , url = tokenUrl
        , scope = scopes
        , token = accessToken.refreshToken
        }
        |> Http.request

It seems that the library does not include the client_id in the form body; when supplied in credentials it just uses it in the headers rather than the body:

makeTokenRequestWith : GrantType -> Json.Decoder success -> Dict String String -> (Result Http.Error success -> msg) -> Authentication -> RequestParts msg
makeTokenRequestWith grantType decoder extraFields toMsg { credentials, scope, token, url } =
    let
        body =
            [ Builder.string "grant_type" (grantTypeToString grantType)
            , Builder.string "refresh_token" (extractTokenString token)
            ]
                |> urlAddList "scope" scope
                |> urlAddExtraFields extraFields
                |> Builder.toQuery
                |> String.dropLeft 1

        headers =
            makeHeaders credentials
    in
    makeRequest decoder toMsg url headers body

It seems like this client_id in the refresh token request is NOT mentioned in RFC: https://datatracker.ietf.org/doc/html/rfc6749#section-6

So maybe it is just strange that spotify auth server is requesting it: https://developer.spotify.com/documentation/web-api/tutorials/refreshing-tokens
Screen Shot 2024-07-10 at 01 03 06


Small nit as well, this documentation was a bit confusing

- `token` (_REQUIRED_):
:

  - `token` (_REQUIRED_):
    Token endpoint of the resource provider

I think this is supposed to be something more like "the refresh token issued by the authorization provider"

@j-krose
Copy link
Author

j-krose commented Jul 9, 2024

Side note, really cool and useful library! Well documented and works really nicely!

I am happy to implement this one myself with some guidance on whether this actually merits a change or not, but I was not sure because I do not know so much about OAuth.

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

No branches or pull requests

1 participant