I need to implement a cross-domain SSO solution. Let's assume I have a-site.com
, b-site.com
and sso-site.com
.
The requirements are as follows:
- Unlogged user clicking "Login" on
a-site.com
is shown a login screen hosted onsso-site.com
. - If the user logged in as above, and subsequently visits
b-site.com
, they will be immediately logged in. I.e. instead of a "Login" link, we want to display their username, etc - without the need to click anything, or a quick redirect of the entire page tosso-site.com
and back.
It seems to me the following scheme, using OAuth2 / OpenID Connect, with a small modification should do it:
- User is unlogged to
a-site.com
,b-site.com
andsso-site.com
. - User goes to
a-site.com
, clicks "Login". - Browser is redirected to
sso-site.com
, with return URL ona-site.com
as a query string param. sso-site.com
server produces a login form, sends to user's browser. User provides credentials.sso-site.com
server checks credentials against DB, decides they are OK.sso-site.com
responds with a redirect to the URL indicated in param in step 3. The URL has an authorization code attached as param. The redirect response also sets a session cookie (on domainsso-site.com
of course).- Browser receives redirect response, sends it to
a-site.com
.a-site.com
server queriessso-site.com
in the backend (not through user's browser) with the authorization code from the redirect URL.sso-site.com
recognizes the authorization code, gives back an access token. If this is OpenID Connect,a-site.com
also gets user info on that response. If not (plain OAuth2), it needs to make another backend call tosso-site.com
to get them.a-site.com
creates a user session, and on the page sent to the browser includes a session cookie (for domaina-site.com
). - From now on, user is obviously logged into
a-site.com
. - User goes to
b-site.com
. - This is where we stray from the standard OAuth2 flow. There's some Javascript in the page, which silently sends a CORS query to
sso-site.com
. Obviously, we have a session cookie on this request.sso-site.com
recognizes the cookie and returns a new authorization code in the payload. - On receiving the response, Javascript recognizes that it got an authorization code (and therefore the user is logged into SSO), so it forces a page reload, attaching the authorization code as a query string param.
b-site.com
server sees the authorization code in a param, so in the backend it does the same thing asa-site.com
did above. This results in user being logged intob-site.com
.
I should add to this that if a user is not logged into SSO, when we make the silent JS call, sso-site.com
returns some payload indicating that. Then, the JS receiving that payload sets a cookie on b-site.com
, whose presence means not to query sso-site.com
via JS on subsequent page views.
Questions:
- should this work (any incorrect assumptions?)
- can it be simplified anywhere (iframes?)
- is this secure (especially in the JS part, departing from OAuth browser redirect model)?
Many thanks! There's a lot of examples on the web for SSO, especially with OAuth2 and CAS (which has a similar flow) - but I could not find a recipe for these specific requirements: cross-domain, and with automatic login without entire page redirect (bad for latency and crawlers) on b-site.com
. The closest is the Stackoverflow SSO guide (here), but they have some extra requirements I don't have.
0 comments:
Post a Comment