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

SSO: Invalid redirect URI when using Azure OIDC or SAML 2.0 #2500

Closed
1 task done
Tracked by #2480
ErikHumphrey opened this issue Dec 15, 2022 · 14 comments · Fixed by #2847
Closed
1 task done
Tracked by #2480

SSO: Invalid redirect URI when using Azure OIDC or SAML 2.0 #2500

ErikHumphrey opened this issue Dec 15, 2022 · 14 comments · Fixed by #2847
Labels
bug bw-unified-deploy An Issue related to Bitwarden unified deployment

Comments

@ErikHumphrey
Copy link

ErikHumphrey commented Dec 15, 2022

Steps To Reproduce

  1. Start up Bitwarden from image: bitwarden/self-host:dev with SSO enabled.
    (The same issue was also encountered using the beta tag.)
    The internal port of the Bitwarden container is 8080.
    An Nginx termination proxy is in front of it; you can access the Bitwarden web client at https://bitwarden.domain.com (i.e., port 443).
  2. Create an organization in Bitwarden and activate an Enterprise licence.
  3. Follow Azure OIDC Implementation or Azure SAML Implementation to set up OIDC or SAML 2.0 with Microsoft Azure.
  4. Sign in from your Bitwarden web client using enterprise single sign-on (e.g., at https://bitwarden.domain.com/#/sso).
  5. Before seeing any Microsoft login screen, you will see an error page similar to:

    Error: invalid_request

    There was an unexpected error during single sign-on.
    Request ID: 0HMMUM26RJOQ9:00000002

The same error will have appeared regardless of whether you used SAML or OIDC.
Redirect behaviour and binding type also do not matter.

Expected Result

Enterprise sign-in with Azure OIDC / Azure SAML 2.0 works as expected, bringing you to a Microsoft AAD log-in screen and signing you into the Bitwarden server.

Actual Result

Enterprise sign-in with Azure OIDC / Azure SAML 2.0 fails. Before seeing a Microsoft AAD login screen, you see the above error message at https://bitwarden.domain.com/sso/Error?errorId=REDACTED

Screenshots or Videos

Screenshot 2022-12-15 at 10 56 39 AM

Screenshot 2022-12-15 at 10 54 37 AM

Additional Context

I tried contacting Bitwarden's technical support team regarding this, but the confirmation email never showed up. Nvm; the site says there's a confirmation email but it goes through anyway without one.

These requests appear in the Nginx server logs after clicking the "Log in" button shown above.

"GET /identity/account/prevalidate?domainHint=foo HTTP/1.1" 200 328 "https://bitwarden.domain.com/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36" "-"
"GET /identity/connect/authorize?client_id=web&redirect_uri=https%3A%2F%2Fbitwarden.domain.com%2Fsso-connector.html&response_type=code&scope=api%20offline_access&state=REDACTEDx_identifier=foo&code_challenge=REDACTED&code_challenge_method=S256&response_mode=query&domain_hint=foo&ssoToken=BWUserPrefix_REDACTED HTTP/1.1" 302 0 "https://bitwarden.domain.com/"
"GET /identity/Account/Login?ReturnUrl=%2Fidentity%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3Dweb%26redirect_uri%3Dhttps%253A%252F%252Fbitwarden.domain.com%252Fsso-connector.html%26response_type%3Dcode%26scope%3Dapi%2520offline_access%26state%3DREDACTEDx_identifier%253Dfoo%26code_challenge%3DREDACTED%26code_challenge_method%3DS256%26response_mode%3Dquery%26domain_hint%3Dfoo%26ssoToken%3DBWUserPrefix_REDACTED HTTP/1.1" 302 0 "-"
"GET /identity/account/ExternalChallenge?domainHint=foo&returnUrl=%2Fidentity%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3Dweb%26redirect_uri%3Dhttps%253A%252F%252Fbitwarden.domain.com%252Fsso-connector.html%26response_type%3Dcode%26scope%3Dapi%2520offline_access%26state%3DREDACTEDx_identifier%253Dfoo%26code_challenge%3DREDACTED%26code_challenge_method%3DS256%26response_mode%3Dquery%26domain_hint%3Dfoo%26ssoToken%3DBWUserPrefix_REDACTED&ssoToken=BWUserPrefix_REDACTED HTTP/1.1" 302 0 "-"
"GET /sso/connect/authorize?client_id=oidc-identity&redirect_uri=http%3A%2F%2Fbitwarden.domain.com%2Fidentity%2Fsignin-oidc&response_type=code&scope=openid%20profile&code_challenge=REDACTED&code_challenge_method=S256&response_mode=form_post&nonce=REDACTED&domain_hint=foo&organizationId=REDACTED&ssoToken=BWUserPrefix_REDACTED&state=REDACTED&x-client-SKU=ID_NETSTANDARD2_0&x-client-ver=6.10.0.0 HTTP/1.1" 302 0 "-"
"GET /sso/Error?errorId=REDACTED HTTP/1.1" 200 764 "-"

I'm not really sure what the issue is here. At one point it's using the HTTPS URI and at another point it's using the HTTPS URI, but it's a 302 so maybe it's redirecting correctly. The URL encoded characters could also be causing issues? Not sure. In Azure, my redirect URL is https://bitwarden.domain.com/sso/oidc-signin, with HTTPS. I've taken a look at the code in bitwarden/clients, but I'm not sure what I'm doing wrong.


  • Every other feature seems to work without issue.
  • BW_ENABLE_SSO is set to "true" and the organization has an active Bitwarden Enterprise licence.
  • My BW_DOMAIN is of the format: bitwarden.domain.com
  • For OIDC, my redirect URL is the same that automatically appears when setting up OIDC through the web client: https://bitwarden.domain.com/sso/oidc-signin

Please let me know if this issue may not be unique to Bitwarden Unified and is instead an issue with bitwarden/clients or my configuration.

Githash Version

7cbc4a8-dirty

Environment Details

  • Operating System: Ubuntu 22.04
  • Environment: Docker
  • Hardware: Intel(R) Xeon(R) CPU E5-2673 v3 @ 2.40GHz, 4 GiB RAM (Standard_B2s Azure virtual machine)
  • Bitwarden behind Nginx TLS termination proxy

Database Image

postgres:14.6-alpine

Issue-Link

#2480

Issue Tracking Info

  • I understand that work is tracked outside of Github. A PR will be linked to this issue should one be opened to address it, but Bitwarden doesn't use fields like "assigned", "milestone", or "project" to track progress.
@ErikHumphrey ErikHumphrey added bug bw-unified-deploy An Issue related to Bitwarden unified deployment labels Dec 15, 2022
@ErikHumphrey ErikHumphrey changed the title SSO: Invalid redirect URI when using Azure OIDC SSO: Invalid redirect URI when using Azure OIDC or SAML 2.0 Dec 15, 2022
@Rezkmike
Copy link

Rezkmike commented Dec 15, 2022

I think I got the same error like this before, the internal redirection from identity to sso is wrongly configured as by default is sso:5000. Since I deployed the application in Kubernetes. I changed that value to Kubernetes service address at environment variable globalSettings__baseServiceUri__internalSso.

In your case it might be need to change to localhost? since you using the unified image

@ErikHumphrey
Copy link
Author

ErikHumphrey commented Dec 15, 2022

Hmm, I could see it being something like that that. I tried setting globalSettings__baseServiceUri__internalSso to localhost and the sso module errored out and stopped. Does the unified container support all the same environment variables as the regular deployment? I didn't see that one listed.

I also tried setting it to: bitwarden (the service/container name), with ports, etc.; the sso service always crashes and stops.

Is there any other way I can change the redirect URI on the application side? Can't/shouldn't change BW_DOMAIN, of course. Could be a red herring too?

@kspearrin
Copy link
Member

@ErikHumphrey Any errors logged from the SSO or Identity application under /etc/bitwarden/logs?

@ErikHumphrey
Copy link
Author

ErikHumphrey commented Dec 15, 2022

@kspearrin identity.log has nothing for this one. Here's what sso.log has:

2022-12-15 18:44:51.616 +00:00 [ERR] Invalid redirect_uri: http://bitwarden.dev.rcgtconsulting.io/identity/signin-oidc
{"ClientId":"oidc-identity","ClientName":null,"RedirectUri":null,"AllowedRedirectUris":["https://bitwarden.domain.com/identity/signin-oidc"],"SubjectId":"anonymous","ResponseType":null,"ResponseMode":null,"GrantType":null,"RequestedScopes":"","State":null,"UiLocales":null,"Nonce":null,"AuthenticationContextReferenceClasses":null,"DisplayMode":null,"PromptMode":"","MaxAge":null,"LoginHint":null,"SessionId":null,"Raw":{"client_id":"oidc-identity","redirect_uri":"http://bitwarden.domain.com/identity/signin-oidc","response_type":"code","scope":"openid profile","code_challenge":"redacted","code_challenge_method":"S256","response_mode":"form_post","nonce":"redacted","domain_hint":"foo","organizationId":"redacted","ssoToken":"BWUserPrefix_redacted","state":"redacted","x-client-SKU":"ID_NETSTANDARD2_0","x-client-ver":"6.10.0.0"},"$type":"AuthorizeRequestValidationLog"}
2022-12-15 18:44:51.616 +00:00 [ERR] Request validation failed

Looks like the redirect_uri it's using with http:// doesn't match the only AllowedRedirectUris which uses https://.

Edit: Thanks for the replies; I'll investigate this more next week or two.

@kspearrin
Copy link
Member

Hmm, we need to figure out how to get Identity to redirect to SSO with https. I imagine this is happening because somewhere is not respecting your proxied protocol. Maybe something can be set in your nginx proxy to properly forward the protocol? I am not an expert with Nginx.

@Rezkmike
Copy link

Rezkmike commented Dec 16, 2022

@ErikHumphrey , After I checked in the container, its whether like the SSO not enable by default (need to add sso env enable yes or something) or just the NGINX routing is not there. If you go to /etc/nginx/http.d/bitwarden.conf there is no SSO location configured, you may need to add the sso block inside this file.

@kspearrin
Copy link
Member

@Rezkmike you just need to set BW_ENABLE_SSO to true to get that going. @ErikHumphrey mentioned that he already did that.

@ErikHumphrey
Copy link
Author

Wasn't able to pull off anything with the Nginx configuration, I don't see any issues there. It likely needs a change on the Bitwarden end & is web server/proxy-agnostic. Assuming it's unique to Unified, I'll try the main deployment in the meantime.

@sniper7kills
Copy link

sniper7kills commented Jan 17, 2023

I was having the same issue and was able to resolve it by:

  1. Enabling SSL
  2. Ensuring my load balancer was sending traffic to the SSL port

It would be nice to not need to enable SSL on the container when my load balancer is already doing SSL termination.


I also had to edit /etc/nginx/http.d/bitwarden.conf and add a / after sso

location /sso/ {
    proxy_pass http://localhost:5007;
    include /etc/nginx/security-headers-ssl.conf;
    include /etc/nginx/security-headers.conf;
    add_header X-Frame-Options SAMEORIGIN;
  }

Otherwise, the sso-connector.html file didn't load properly.

@wizpresso-steve-cy-fan
Copy link

wizpresso-steve-cy-fan commented Jan 19, 2023

@sniper7kills Although enabling SSL did work, but some of us are hosting Bitwarden behind an IIS proxy, and IIS does not support SSL passthrough.

We also had leveraged our IIS infrastructure as our SSL offloading proxy.

We tried disabling SSL on unified and set X-Forwarded-Proto but it still doesn't help. The redirect URL generated by Bitwarden is still http. We tried to set redirect URL in Azure AD to also allow http, but that is not allowed because Azure AD required https for redirect URIs unless it is localhost

@kspearrin
Copy link
Member

kspearrin commented Apr 11, 2023

I have reproduced this and traced the issue back to our proxy.conf file here:
https://github.com/bitwarden/server/blob/master/docker-unified/nginx/proxy.conf#L6

Setting the following values manually to https solves the issue:

proxy_set_header        X-Url-Scheme      https;
proxy_set_header        X-Forwarded-Proto https;

This is because in order to properly handle redirects, ASP.NET Core requires that X-Forwarded-Proto be properly set. See docs here: https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-7.0

We already do all of this. The problem seems to manifest itself whenever using more than one proxy server. Internally, the Bitwarden unified container is already running a nginx proxy and is directing traffic to various ASP.NET Core applications running at http://localhost:5xxx. In front of that, I have another nginx proxy that terminates SSL and is directing traffic from the public host to the unified container. So you end up with a chain that looks something like this:

1. https://bitwarden.mydomain.com/identity (public nginx proxy)
2.    => http://bitwarden:8080/identity (unified nginx proxy)
3.          => http://localhost:5005 (ASP.NET Core Identity application)

With this chain, you can see the $scheme that is forwarded from step 2 to 3 is http, which is what ASP.NET Core then interprets as the protocol of the running application and is used for these SSO redirects. This is also why things start working when configuring BW_ENABLE_SSL=true, because you are changing the protocol from http => https in step 2 and $scheme now matches the upstream public $scheme.

As I mentioned earlier, you could just hardcode the https value rather than using the upstream $scheme. I don't particularly like this solution since it's not very dynamic.

I am not a nginx expert, but does anyone know of a way to handle this dynamically? We need some way to see what the original upstream host and protocol is to properly pass through the chain of proxies.

@ErikHumphrey
Copy link
Author

ErikHumphrey commented Apr 11, 2023

I'm not an Nginx expert either and can't test this at the moment, but would work if we set X-Forwarded-Proto to the upstream public Nginx proxy value (if set) and $scheme otherwise?

Upstream public proxy:

proxy_set_header X-Forwarded-Proto $scheme;

Bitwarden Unified proxy:

proxy_set_header X-Forwarded-Proto $scheme; # Normally empty by default, but set upstream

That could cause issues if you don't have an upstream proxy as it needs to be set, as you said. So something like:

proxy_set_header X-Forwarded-Proto $scheme;
if ($http_x_forwarded_proto) {
  proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
}

or something similar to that effect:

set $forwarded_proto $http_x_forwarded_proto;
if ($forwarded_proto = '') {
    set $forwarded_proto $scheme;
}
proxy_set_header X-Forwarded-Proto $forwarded_proto;

@kspearrin
Copy link
Member

kspearrin commented Apr 11, 2023

I think I got this working with something like

map $http_x_forwarded_proto $proto_scheme {
    default "$scheme";
    ~. "$http_x_forwarded_proto";  # Regular expression to match any value
}

proxy_set_header        X-Url-Scheme      $proto_scheme;
proxy_set_header        X-Forwarded-Proto $proto_scheme;

This null coalesces the upstream X-Forwarded-Proto header and defaults back to $scheme if not set.

@kspearrin
Copy link
Member

kspearrin commented Apr 13, 2023

#2847 should resolve the issue. Feel free to try the dev tag from DockerHub for now if you want to confirm.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug bw-unified-deploy An Issue related to Bitwarden unified deployment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants