okta / okta-signin-widget

HTML/CSS/JS widget that provides out-of-the-box authentication UX for your organization's apps
Other
376 stars 319 forks source link

idpDiscovery: deep link relay state ignores hostname on post back to okta #1264

Open rcollette opened 4 years ago

rcollette commented 4 years ago

:information_source: If you have a question, please post it on the Okta Developer Forum instead. Issues in this repository are reserved for bug reports and feature requests.

I'm submitting a

Background info

I am using the idpDiscovery feature, which winds up routing to Microsoft as a SAML Identity Provider (IDP).

The post back to Okta Service Provider (SP) includes a RelayState that is the fully qualified URL back to the application where the widget is being used (ex. http://localhost:4041/sign-in), having been set from window.location.href.

Expected behavior

After the post to Okta (SP) the client should be redirected back to my application, including the proper host name.

What went wrong?

After the POST to Okta (SP), Okta redirects to the current host (SP) with the path of the URL provided in the RelayState parameter. The protocol and host portion of the relayState is ignored.

Steps to reproduce

As a developer, I don't have the authority to setup a full flow, including a Microsoft IDP, that can demonstrate this, but I will provide as much relevant information as I can.

Widget configuration

    this._widget = new OktaSignIn({
      baseUrl: 'https://' + this._oktaConfig.domain,
      authParams: {
        pkce: true
      },
      features: {
        rememberMe: true,
        showPasswordToggleOnSignInPage: true,
        idpDiscovery: true
      },
      idpDiscovery: {
        requestContext: window.location.href
      }
    });

The client calls webfinger

curl 'https://host/.well-known/webfinger?resource=okta%3Aacct%3Arichard.collette%40org.com&requestContext=https%3A%2F%2Flocalhost%3A4041%2Fsign-in' \
  -H 'Connection: keep-alive' \
  -H 'Pragma: no-cache' \
  -H 'Cache-Control: no-cache' \
  -H 'sec-ch-ua: "Google Chrome";v="83"' \
  -H 'x-okta-user-agent-extended: okta-signin-widget-4.1.3' \
  -H 'accept-language: en' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36' \
  -H 'content-type: application/json' \
  -H 'accept: application/jrd+json' \
  -H 'DNT: 1' \
  -H 'Origin: https://localhost:4041' \
  -H 'Sec-Fetch-Site: cross-site' \
  -H 'Sec-Fetch-Mode: cors' \
  -H 'Sec-Fetch-Dest: empty' \
  --compressed

With response

{
    "subject": "okta:acct:richard.collette@org.com",
    "links": [
        {
            "rel": "okta:idp",
            "href": "https://host/sso/idps/0oarl4yesaLyKtpGR0h7?fromURI=%2Fhelpme&login_hint=richard.collette%40org.com#",
            "titles": {
                "und": "OrgEmployees"
            },
            "properties": {
                "okta:idp:metadata": "https://host/api/v1/idps/0oarl4yesaLyKtpGR0h7/metadata.xml",
                "okta:idp:type": "SAML2",
                "okta:idp:id": "0oarl4yesaLyKtpGR0h7"
            }
        }
    ]
}

I'm going to skip the initiation of the SAML flow at this point but the post back from Microsoft idp looks like:

curl 'https://host/sso/saml2/0oarl4yesaLyKtpGR0h7' \
  -H 'Connection: keep-alive' \
  -H 'Pragma: no-cache' \
  -H 'Cache-Control: no-cache' \
  -H 'sec-ch-ua: "Google Chrome"; v="83"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'Origin: https://login.microsoftonline.com' \
  -H 'Upgrade-Insecure-Requests: 1' \
  -H 'DNT: 1' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36' \
  -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9' \
  -H 'Sec-Fetch-Site: cross-site' \
  -H 'Sec-Fetch-Mode: navigate' \
  -H 'Sec-Fetch-Dest: document' \
  -H 'Referer: https://login.microsoftonline.com/' \
  -H 'Accept-Language: en-US,en;q=0.9,fr-CA;q=0.8,fr;q=0.7' \
  -H 'Cookie: JSESSIONID=1D803AD28673511E49478D57BC6658CD; t=default; DT=DI09jz29L1TSxOUs-wTq-v91Q' \
  --data-raw 'SAMLResponse=PHNhbWxwOlJlc3BvbnNlIElEPSJfOWVhYTFjZDEtYjExYi00M2JhLWI2ZGQtMTRlZTk2ZGNkZGU1IiBWZXJzaW9uPSIyLjAiIElzc3VlSW5zdGFudD0iMjAyMC0wNi0yNVQyMDozMDozNS4wMjVaIiBEZXN0aW5hdGlvbj0iaHR0cHM6Ly9zc28ucHJlY2lzZWx5LnNlcnZpY2VzL3Nzby9zYW1sMi8wb2FybDR5ZXNhTHlLdHBHUjBoNyIgSW5SZXNwb25zZVRvPSJpZDkwODI0MjkxNjM2ODY0ODMxMjk3MDMzNzU2IiB4bWxuczpzYW1scD0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnByb3RvY29sIj48SXNzdWVyIHhtbG5zPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIj5odHRwczovL3N0cy53aW5kb3dzLm5ldC9jMGEyOTQxYy0yOTE1LTRiY2EtYWE0Yy1lODg4MGRjNzdmN2YvPC9Jc3N1ZXI%2BPHNhbWxwOlN0YXR1cz48c2FtbHA6U3RhdHVzQ29kZSBWYWx1ZT0idXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOnN0YXR1czpTdWNjZXNzIi8%2BPC9zYW1scDpTdGF0dXM%2BPEFzc2VydGlvbiBJRD0iXzYxYWZhYTU4LWQ4OWUtNGQ1OC05MDRjLTYwZjZhMWEzZDIwMCIgSXNzdWVJbnN0YW50PSIyMDIwLTA2LTI1VDIwOjMwOjM1LjAyNVoiIFZlcnNpb249IjIuMCIgeG1sbnM9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iPjxJc3N1ZXI%2BaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvYzBhMjk0MWMtMjkxNS00YmNhLWFhNGMtZTg4ODBkYzc3ZjdmLzwvSXNzdWVyPjxTaWduYXR1cmUgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvMDkveG1sZHNpZyMiPjxTaWduZWRJbmZvPjxDYW5vbmljYWxpemF0aW9uTWV0aG9kIEFsZ29yaXRobT0iaHR0cDovL3d3dy53My5vcmcvMjAwMS8xMC94bWwtZXhjLWMxNG4jIi8%2BPFNpZ25hdHVyZU1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZHNpZy1tb3JlI3JzYS1zaGEyNTYiLz48UmVmZXJlbmNlIFVSST0iI182MWFmYWE1OC1kODllLTRkNTgtOTA0Yy02MGY2YTFhM2QyMDAiPjxUcmFuc2Zvcm1zPjxUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjZW52ZWxvcGVkLXNpZ25hdHVyZSIvPjxUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiLz48L1RyYW5zZm9ybXM%2BPERpZ2VzdE1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZW5jI3NoYTI1NiIvPjxEaWdlc3RWYWx1ZT5sa1RBKzQvdUdVSkJoZllOMG5sYjBTVkQ5UGRDNlp1Q2FTZnk5WVVpaXNJPTwvRGlnZXN0VmFsdWU%2BPC9SZWZlcmVuY2U%2BPC9TaWduZWRJbmZvPjxTaWduYXR1cmVWYWx1ZT5WcGtTcEFndHRVdldhUnNHYnl5YUVBQXVBZ2g4M3E5N1EraVNJdzRBMU9ZYk9TSkJGVnVkV3BjdXprZExRanp1dk5IeXRqLzM3RDF1RVVvNlgwemdKNUExRWg4NllEOENFOVB5VnFzdVZsNVJQb3ZCSzZFeVUydnNkUSs3M3RCWG9CQlhBM2g1N3gvdU9DYkZTZ0JtZ0g4QXVxUmo2d0JtYWRlTEd1cEI5QnlrbmswbmJreDYzOFZrbWtoK0F5UkdGT0h1OFZweGp2dUdiQlpYcTN4Z3BNYitRWG1wTFlkQ2J2ZGt6RkxJN09kdkRZajRLdElwQjJacHIvL3ZEanZMZ2RWUTR4cnNxd0lkMENOZDVFKzJUcHowL3ZPZVFQNmU4VjgzWHcxL1ltS1FSaDY1MVRxUjNrUmhRRUdCanM5Y0UvbVdHSmkvS3VJZEtYdWRSWktBSWc9PTwvU2lnbmF0dXJlVmFsdWU%2BPEtleUluZm8%2BPFg1MDlEYXRhPjxYNTA5Q2VydGlmaWNhdGU%2BTUlJQzhEQ0NBZGlnQXdJQkFnSVFRY0VHSEx4UTVaeEZIN3Iwb0VPSnV6QU5CZ2txaGtpRzl3MEJBUXNGQURBME1USXdNQVlEVlFRREV5bE5hV055YjNOdlpuUWdRWHAxY21VZ1JtVmtaWEpoZEdWa0lGTlRUeUJEWlhKMGFXWnBZMkYwWlRBZUZ3MHlNREExTVRneE16RTJNVFZhRncweU16QTFNVGd4TXpFMk1UVmFNRFF4TWpBd0JnTlZCQU1US1UxcFkzSnZjMjltZENCQmVuVnlaU0JHWldSbGNtRjBaV1FnVTFOUElFTmxjblJwWm1sallYUmxNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQWwvS1dXajRnK2dIcC9QM2VwL2ZFTTFLT25JSGJvTERZS3BKQlpvNWlBay8rTkpRS0kveDVPdTc2T0wvdDF1ZVJzNWxHVDJlSzNEeEZjZWVnVDRGQ01hTDBEK2tteVM2T24vUEpRTzZNZEQyZS9RWi9nNEUweDVaYlBjd0tpdjlqcnhEb2N6MGFTM2hkbWF1R2xLbElvbGo5UVcrVGEyTzF5QVlhRFFmVXBCRkFNNndjWkxHUi8wVkErVWpBNTd5QzE5MHFzOHN1em5rLzIzNTVqalRsdS9PNnYrT1JvTEZHakJ3YnpaM3VlWk1HU3J3bFRHRlUwZWY2UjlCclRaVFRFUXJDUVV2NFJaeXI5RCt2eW41NkhNY21HT0VBc3Arc2NkajVvZ2laY3ZtZ2ZhWXhDWUd0RlQ4VG8ybGdYUkhXZ3lNbU1lWjRSYTc2WlBjaW1keld2UUlEQVFBQk1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQjd2OHlKdFo3RVY1YmFEajN1VHo1aGRQalMvcWhHSDY0YS95SGFwcEErTTJrdm1qVzByVS9VaC90U0FYWGRYdjZjZkMyejVxaE5jTUFreWR3S3dydmNxalBXVWpHSHk4RTJ5MURhZXNZTkRrQzI2RUhsY0ZMdWJlazJQUUlxWGsvaEJXTzJEa3g2WmZOZnZXL2hhTVdPVDA1c2oxbllVSnpoTGUrRXpRdGczYkNZc0RzK3ZDSHpneDRyckxaMUQ3b0Jka3JIS2UvcDRBMTZrcUlYM2pMRXE3UTJ4cEQwbW8vbzNkRnoyZUllREQ5MU5PN0FROFFCYXUvdW1hakk3YVFCd2VONGNhOUhIVnBFcVk0SXVrUm9WdWZhR0YvV3JoMTZtelFGeDZTeUcrRVFZWnQzR3V2cTU5em5kRnRSWXJWYjZ6TVFlZkNUNnhYbGVXeitiKzJEPC9YNTA5Q2VydGlmaWNhdGU%2BPC9YNTA5RGF0YT48L0tleUluZm8%2BPC9TaWduYXR1cmU%2BPFN1YmplY3Q%2BPE5hbWVJRCBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjEuMTpuYW1laWQtZm9ybWF0OmVtYWlsQWRkcmVzcyI%2BUmljaGFyZC5Db2xsZXR0ZUBwcmVjaXNlbHkuY29tPC9OYW1lSUQ%2BPFN1YmplY3RDb25maXJtYXRpb24gTWV0aG9kPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6Y206YmVhcmVyIj48U3ViamVjdENvbmZpcm1hdGlvbkRhdGEgSW5SZXNwb25zZVRvPSJpZDkwODI0MjkxNjM2ODY0ODMxMjk3MDMzNzU2IiBOb3RPbk9yQWZ0ZXI9IjIwMjAtMDYtMjVUMjE6MzA6MzQuNzU5WiIgUmVjaXBpZW50PSJodHRwczovL3Nzby5wcmVjaXNlbHkuc2VydmljZXMvc3NvL3NhbWwyLzBvYXJsNHllc2FMeUt0cEdSMGg3Ii8%2BPC9TdWJqZWN0Q29uZmlybWF0aW9uPjwvU3ViamVjdD48Q29uZGl0aW9ucyBOb3RCZWZvcmU9IjIwMjAtMDYtMjVUMjA6MjU6MzQuNzU5WiIgTm90T25PckFmdGVyPSIyMDIwLTA2LTI1VDIxOjMwOjM0Ljc1OVoiPjxBdWRpZW5jZVJlc3RyaWN0aW9uPjxBdWRpZW5jZT5odHRwczovL3d3dy5va3RhLmNvbS9zYW1sMi9zZXJ2aWNlLXByb3ZpZGVyL3Nwdmd2b2JvYWlxc3ZpbnN6YXV1PC9BdWRpZW5jZT48L0F1ZGllbmNlUmVzdHJpY3Rpb24%2BPC9Db25kaXRpb25zPjxBdHRyaWJ1dGVTdGF0ZW1lbnQ%2BPEF0dHJpYnV0ZSBOYW1lPSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL2lkZW50aXR5L2NsYWltcy90ZW5hbnRpZCI%2BPEF0dHJpYnV0ZVZhbHVlPmMwYTI5NDFjLTI5MTUtNGJjYS1hYTRjLWU4ODgwZGM3N2Y3ZjwvQXR0cmlidXRlVmFsdWU%2BPC9BdHRyaWJ1dGU%2BPEF0dHJpYnV0ZSBOYW1lPSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL2lkZW50aXR5L2NsYWltcy9vYmplY3RpZGVudGlmaWVyIj48QXR0cmlidXRlVmFsdWU%2BN2EyOGY4ZmYtZjdhZi00OGMwLWFlZmMtOTdhMDBkNWZiM2RkPC9BdHRyaWJ1dGVWYWx1ZT48L0F0dHJpYnV0ZT48QXR0cmlidXRlIE5hbWU9Imh0dHA6Ly9zY2hlbWFzLm1pY3Jvc29mdC5jb20vaWRlbnRpdHkvY2xhaW1zL2Rpc3BsYXluYW1lIj48QXR0cmlidXRlVmFsdWU%2BUmljaGFyZCBDb2xsZXR0ZTwvQXR0cmlidXRlVmFsdWU%2BPC9BdHRyaWJ1dGU%2BPEF0dHJpYnV0ZSBOYW1lPSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL2lkZW50aXR5L2NsYWltcy9pZGVudGl0eXByb3ZpZGVyIj48QXR0cmlidXRlVmFsdWU%2BaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvYzBhMjk0MWMtMjkxNS00YmNhLWFhNGMtZTg4ODBkYzc3ZjdmLzwvQXR0cmlidXRlVmFsdWU%2BPC9BdHRyaWJ1dGU%2BPEF0dHJpYnV0ZSBOYW1lPSJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL2NsYWltcy9hdXRobm1ldGhvZHNyZWZlcmVuY2VzIj48QXR0cmlidXRlVmFsdWU%2BaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93cy8yMDA4LzA2L2lkZW50aXR5L2F1dGhlbnRpY2F0aW9ubWV0aG9kL3Bhc3N3b3JkPC9BdHRyaWJ1dGVWYWx1ZT48L0F0dHJpYnV0ZT48QXR0cmlidXRlIE5hbWU9Imh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL2dpdmVubmFtZSI%2BPEF0dHJpYnV0ZVZhbHVlPlJpY2hhcmQ8L0F0dHJpYnV0ZVZhbHVlPjwvQXR0cmlidXRlPjxBdHRyaWJ1dGUgTmFtZT0iaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNS8wNS9pZGVudGl0eS9jbGFpbXMvc3VybmFtZSI%2BPEF0dHJpYnV0ZVZhbHVlPkNvbGxldHRlPC9BdHRyaWJ1dGVWYWx1ZT48L0F0dHJpYnV0ZT48QXR0cmlidXRlIE5hbWU9Imh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL2VtYWlsYWRkcmVzcyI%2BPEF0dHJpYnV0ZVZhbHVlPlJpY2hhcmQuQ29sbGV0dGVAcHJlY2lzZWx5LmNvbTwvQXR0cmlidXRlVmFsdWU%2BPC9BdHRyaWJ1dGU%2BPEF0dHJpYnV0ZSBOYW1lPSJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIj48QXR0cmlidXRlVmFsdWU%2BUmljaGFyZC5Db2xsZXR0ZUBwcmVjaXNlbHkuY29tPC9BdHRyaWJ1dGVWYWx1ZT48L0F0dHJpYnV0ZT48L0F0dHJpYnV0ZVN0YXRlbWVudD48QXV0aG5TdGF0ZW1lbnQgQXV0aG5JbnN0YW50PSIyMDIwLTA2LTI1VDIwOjMwOjI5LjE3MVoiIFNlc3Npb25JbmRleD0iXzYxYWZhYTU4LWQ4OWUtNGQ1OC05MDRjLTYwZjZhMWEzZDIwMCI%2BPEF1dGhuQ29udGV4dD48QXV0aG5Db250ZXh0Q2xhc3NSZWY%2BdXJuOm9hc2lzOm5hbWVzOnRjOlNBTUw6Mi4wOmFjOmNsYXNzZXM6UGFzc3dvcmQ8L0F1dGhuQ29udGV4dENsYXNzUmVmPjwvQXV0aG5Db250ZXh0PjwvQXV0aG5TdGF0ZW1lbnQ%2BPC9Bc3NlcnRpb24%2BPC9zYW1scDpSZXNwb25zZT4%3D&RelayState=https%253A%252F%252Flocalhost%253A4041%252Fsign-in' \
  --compressed

Note the RelayState at the very end of the raw data in that curl. It is the requestContext that was originally set using window.location.href, so it is "correct".

However, the response to that POST is a 302 redirect to the SP, https://host/sign-in?fromLogin=true, rather than to localhost.

I have referenced the following two sources regarding deep links: https://developer.okta.com/docs/reference/api/idps/#redirect-with-saml-deep-links https://devforum.okta.com/t/how-do-i-find-app-location/2630/4

However, as far as I am aware, as a client application, I am not able to control the creation of the POST from the Idp to the SP to include app-location and app-id in the POST URL back to the SP.

We do have a hosted login page that does not use the widget, it first makes an /authorize call that contains the redirect uri (again a full url to a client that includes protocol and domain) and when going to Microsoft, the relay state is

%2Foauth2%2Fv1%2Fauthorize%2Fredirect%3Fokta_key%3D2hwYiuN-rOu5rehrj_ZrRAT-6DzUG0ZsUrS4CsPHqyI

I imagine that the callback to /oauth2/authorize/redirect with okta_key is in some way enabling the redirect to the client properly.

Your environment

jayhoogle commented 3 years ago

@rcollette did you ever find a solution to this? We're currently experiencing the same issue, and I'm trying to see how an okta_key can be generated to enable the redirection to work.

rcollette commented 3 years ago

@jayhoogle - I did not. I had to abandon the widget. I had a support ticket that went round and round between people and never got resolved. It was a bad customer experience.

shuowu commented 3 years ago

@rcollette Just want to check if you have added localhost to the trust origin?

rcollette commented 3 years ago

Yes I did.

shuowu commented 3 years ago

@rcollette Thanks for the report.

Internal investigation ref: OKTA-354752