providers: add okta (take two)
Follow-up to #406 to rebase and add missing ValidateSessionState method.
@asms and @rothgar, mind testing this version?
That's great thanks. I can test it tomorrow. Is there a way to reproduce the original bug this addresses?
This provider is testing fine for me but I'm curious about where the X-Forwarded-User gets set. I tried adding a GetUserName function to the provider but it doesn't look like it's being used as I would have expected. I'm probably doing something wrong but I haven't spent too much time looking at the code.
From what I can tell the X-Forwarded-User header is simply taking the email address and stripping off the @domain. That's not always ideal as sometimes usernames and email addresses are different.
Looking at the payload returned from okta can someone point me in the right direction to change the passed header to look at the preferred_username?
@rothgar Good catch! Just implemented that for you in my latest commit. Can you pull down and test again?
Funny because I added that exact same block of code and it doesn't look like it works the way I would have expected.
When I add that block of code I also added a debug line to print the json from userinfo in the logs. I can see preferred username is set as I would expect but the HTTP_X_FORWARDED_USER header that gets passed to the upstream endpoint is still set to the first part of the email address.
I also see in the logs that the user doesn't have a value
authentication complete Session{email:[email protected] user: token:true}
I suspect there's somewhere else that needs to be updated to tell the main proxy that the provider.
I looked in the proxy itself and it looks like it should try by default but I'm not sure that's happening
https://github.com/bitly/oauth2_proxy/blob/1209c63b58507986df469c0aba8de60100afd477/oauthproxy.go#L248-L255
@rothgar I finally had the time to test this myself, and it all seems to work fine. Can confirm that user is set to the full Okta username (preferred_username). Perhaps the oauth2_proxy binary you're using isn't the one with the addition of that function?
Would love to get this reviewed and landed.
Did you set any specific flags for the proxy when running it? Did you have to change the mapping in Okta for properties at all? I tried a few different different flags but all the defaults are already set to true.
I'll try it again and get some more info around what flags I use and how the app is configured in Okta.
@rothgar Nothing special. I use the config flag only, so mostly defaults. Only options I have set in my config file are http_address, upstreams, email_domains (set to *), provider (set to okta), okta_domain (set to <foo>.okta.com), client_id, client_secret, cookie_name, and cookie_secret. That's it.
No changes in Okta either. I just set up a custom OpenID Connect app, set the right redirect URI, and grabbed the client ID/secret. Super simple.
It's the bare minimum, but it confirmed that I was at least getting the right e-mail and username back from Okta.
I tested again and still am not getting HTTP_X_FORWARDED_USER set to the correct preferred_username variable. Here's how I'm testing so maybe someone can replicate.
I compiled the proxy (pulled these recent changes) and ran it with the following flags
./oauth2_proxy \
--okta-domain $domain.okta.com \
--cookie-secret $cookie_secret \
--email-domain="$domain.com" \
--upstream=http://$hostname.$domain.com \
--provider okta \
--client-secret=$client_secret \
--client-id $client_id \
--http-address="0.0.0.0:4180" \
--redirect-url http://$hostname.$domain.com:4180/oauth2/callback \
--cookie-secure=false
Then I run a simple container with index.php to print the headers passed index.php
<?php
print_r($_SERVER);
?>
Then run
docker run -it --rm -p 80:80 -v $PWD:/var/www/html php:apache
In okta I made the app with http://$hostname.$domain.com:4180/oauth2/callback for the callback
Now browsing to http://$hostname.$domain.com:4180 I log in to okta and am passed the headers
[HTTP_X_FORWARDED_EMAIL] => Justin.Garrison@$domain.com
[HTTP_X_FORWARDED_USER] => Justin.Garrison
However, if I add the --pass-access-token to the proxy I can then take the [HTTP_X_FORWARDED_ACCESS_TOKEN] token and curl the userinfo endpoint with
curl -X POST -H "Authorization: Bearer $TOKEN" \
"https://$domain.okta.com/oauth2/v1/userinfo" \
| jq . \
| grep preferred_username
And I see from there the actual preferred_username is "preferred_username": "jgarr@$domain.com"
I tried checking the application mappings in okta to see if they were set to something different but I couldn't find a field for preferred_username. I deleted the app and created a new one and get the same results. I double checked the code to make sure I was compiling the right thing but still do not get the correct HTTP_X_FORWARDED_USER passed to the application.
@reedloden Okta has support for OpenID Connect. An OIDC priovider was added #389 Therefore, a separate Okta provider may not be necessary (unless okta requires additional API overhead beyond the OIDC spec). However, if you opt to use that instead, I would be cautious; the OIDC provider may have an issue with refreshing the session #523
One reason that a specific Okta provider may be required: for OIDC applications using the Authorization Code flow, Okta does not return groups in the ID token, even when the groups claim is specified. In order to retrieve groups, one must call the /userinfo endpoint with the Access token. This isn't immediately apparent from the documentation, but is my understanding based on recent experience.