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

Issue passing params to callback URL #44

Open
LaurelOlson opened this issue Jan 10, 2024 · 3 comments
Open

Issue passing params to callback URL #44

LaurelOlson opened this issue Jan 10, 2024 · 3 comments

Comments

@LaurelOlson
Copy link

I'm using omniauth-keycloak with devise in a rails + react project and I have keycloak omniauth hooked up successfully for regular login/signup. I'm trying to add it to the devise invitation flow and am running into an issue passing the invitation_token so it is accessible in the omniauth callback endpoint.

I added the param into authorize_options and passed it as a hidden input in the form as per #24 but this doesn't seem to do anything to the callback request. I'm not sure if I'm misunderstanding the feature or if there is something wrong with the config.

I also tried passing the param directly in the form action e.g. action={'/auth/keycloak?invitation_token=${token}'} but this causes an Incorrect redirect_uri error in the callback phase, presumably due to the invitation_token in the query params. The keycloak integration redirect uri is set to http://localhost:3000/*

Relevant code:

# config/initializers/devise.rb
config.omniauth :keycloak_openid,
                  ENV["KEYCLOAK_CLIENT"],
                  ENV["KEYCLOAK_SECRET"],
                  client_options: {
                    site: ENV["KEYCLOAK_AUTH_URL"],
                    realm: "standard",
                  },
                  authorize_options: [:invitation_token],
                  name: :keycloak,
                  strategy_class: OmniAuth::Strategies::KeycloakOpenId
// form.tsx
<form action={`/api/auth/keycloak`} method="post">
    <Input hidden={true} name="invitation_token" value={invitationToken} />
    <input
        type="hidden"
        name="authenticity_token"
        value={document.querySelector("[name=csrf-token]").content}
    />
    <Button type="submit">Login</Button>
</form>
@ushmakapure
Copy link

Keycloak wants the request phase and the callback phase redirect_uri to match exactly. When you call '/auth/keycloak?invitation_token=${token}' I believe Omniauth appends some state and session data to the callback phase (tbh not quite sure where this comes from). To get around this, the gem overrides build_access_token to edit the callback url to strip out all query params.

{:redirect_uri => callback_url.gsub(/\?.+\Z/, "")}

So ultimately, the request phase redirect_uri will include the invitation_token you've passed in from the client, but the callback phase will strip all params, resulting in mismatched redirect_uris and ultimately login failure.

I adapted the gem and ended up implementing something like this to allow the params to be passed through

def build_access_token
        verifier = request.params['code']

        client.auth_code.get_token(verifier,
                                  { redirect_uri: remove_extra_params(request.params, callback_url) }
                                  .merge(token_params.to_hash(symbolize_keys: true)),
                                  deep_symbolize(options.auth_token_params))
 end

# Strips unwanted query params from urls
def remove_extra_params(params, url)
      ignored_params = %w[state session_state iss code]
      accepted_params = params.reject { |k, _v| ignored_params.include?(k) }

      raw_query_string = ''
      accepted_params.each { |k, v| raw_query_string += "#{k}=#{v}&" }
      query = raw_query_string.delete_suffix('&')

      stripped_url = url.gsub(/\?.+\Z/, '')
      query.blank? ? stripped_url : "#{stripped_url}?#{query}"
end

@marvin-min
Copy link

marvin-min commented Nov 23, 2024

I also encountered similar issues. when my redirect_uri does not contains some query parameters, such as /kc/user/auth/cb, it works.
but when a append a parameters it fails. example: /kc/user/auth/cb?origin=/my_profile.

@marvin-min
Copy link

@ushmakapure Thank you for your solution. It works.

The only issue is if your params contains some url(/callback?origin=#{url}), the url needs to be escaped, but for normal case, it doesn't need escape action.

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

3 participants