SAML2.0 Authentication with Node.js and SPA
Asked Answered
B

2

16

I've been scratching my head for about 2 days on how to solve what seemed to be a simple task, but it's starting to drive me crazy.

I have an application where users will use SAML 2.0 to authenticate. I have a react-application set up for the front-end, and was thinking I was gonna use JWT to secure the rest-api communication between front-end and backend.

When a user signs in, the flow is the following:

  1. User accesses www.server.com/ and gets served the static HTML with react-application
  2. User clicks 'Sign in' and accesses www.server.com/login
  3. passport-saml redirects user to saml identity provider. User logs in.
  4. User calls back to www.server.com/callback with a SamlResponse in the req.body which is decoded by passport-saml and put into req.user.
  5. If the user doesn't already exist, I create the user in the database.
  6. I create a JWT.

What should I do next? The problem is that the user is not in the react-application when calling back from the identity provider, so I've lost all state in the application, so whatever I reply with will get sent to the browser.

Is there any way I could force the browser to give me the SamlResponse which the identityprovider is calling back with? Then I could send it to the server as a http-request from the react-application.

Bide answered 16/6, 2017 at 15:38 Comment(1)
hai can u share some sample i have the same questionAnimator
B
21

After some thinking, I came up with the following solution which worked quite nicely for me.

SAML has something called RelayState which is a property that the Service Provider has to respond with. So now the process looks like this:

  1. User accesses http://frontendserver.com and gets server the static page with the React application (not signed in.).
  2. User clicks 'Login' and gets redirected to http://backendserver.com/login/?RelayState=http://frontendserver.com which authenticates via passport-saml and redirects user to SP. So I pass the origin of the request in RelayState.
  3. User calls back to http://backendserver.com/callback with the SamlResponse, which includes the RelayState.
  4. I create a token, and redirect the user to RelayState/#token.
  5. I can then parse the url in the React application, and add the token as a header for any further requests.

This might've seemed like the obvious way to do it, but it took me quite a while to figure out that this would work.

Bide answered 19/6, 2017 at 14:16 Comment(5)
Not as long as the communitcation is done via https.Bide
Can you provide a sample app please?Levorotatory
how to logout and check if token is valid when neext time i come to websiteAnimator
@Animator JWT doesn't have a clean way to log out. What I do on my app is if the user clicks logout, I simply delete their token from the cookies. If you need to log the user out from the server (let's say delete them), you'd have to have a mechanism that keeps track of tokens on the server (db for example) and invalidates them.Respire
Please, can you add more details, please. I get SAMLResponse and redirect to web-app again with 302 status code, but browser prevents any access from JS because of 302. So this step "User calls back to backendserver.com/callback with the SamlResponse, which includes the RelayState." in which way should be done ? Detect redirect ?Pahang
T
0

I know this question is for Node backend, but I found an article of the implementation for a PHP/Apache webserver backend here and I think it can help someone trying to understand the flow of the process of how this type of thing works.

Trigraph answered 1/7, 2019 at 9:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.