We are using the `@boxyhq/saml-jackson` npm packag...
# ory-selfhosting
f
We are using the
@boxyhq/saml-jackson
npm package to convert saml response into a redirect_url as done in the github/ory/polis-examples repo. eg
Copy code
// Handle the SAML Response from IdP
router.post(samlPath, async (req, res, next) => {
  const { RelayState, SAMLResponse } = req.body;

  try {
    const { redirect_url } = await oauthController.samlResponse({ RelayState, SAMLResponse });

    res.redirect(redirect_url);
  } catch (err) {
    next(err);
  }
});
Why does the function,
oauthController.samlResponse({ RelayState, SAMLResponse})
only return the redirect_url, and not the user profile? When the function does get it and use it to generate the code? Why is it necessary to get a code, and then exchange the code for an access token, and then use the access token to get the user profile (s below) when the user profile is available before the code and even used to generate the code?
Copy code
// Callback (Redirect URL)
router.get('/sso/callback', async (req, res, next) => {
  const { code, state } = req.query;

  // TODO: Validate state

  try {
    const { access_token, id_token } = await oauthController.token({
      code,
      client_id: `tenant=${tenant}&product=${product}`,
      client_secret: 'dummy',
      redirect_uri: redirectUrl,
    });

    // Get the profile infor using the access_token
    const { id, email, firstName, lastName } = await oauthController.userInfo(access_token);

    req.session.profile = { id, email, firstName, lastName };

    res.redirect('/profile');
  } catch (err) {
    next(err);
  }
});
The user profile is all that is needed but only available behind 3 unnecessary steps, that seems strange. Is there a way to make it operate like that? To also return the profile with the redirect url?
c
SAML is wrapped around OAuth2, since you are embedding the npm you have to implement all the routes needed to make this happen. It’s simpler to use the service instead if you want to avoid the plumbing.
f
Thanks for the response. We are currently running ory/polis as well to have an admin interface for updating the saml connections etc. But it is rather convenient to use the package inside our own server to do the oauthController.authorize instead of doing manual api calls to the authorize etc endpoints of ory/polis. (Ideally, there would be separate client and server npm packages, where the client npm package just has functionality to interface with the ory/polis service. But that's not important.) Maybe im misunderstanding some part of it, but from implementing it and looking at this diagram, it seems like azure AD could just post samlResponse directly to our own server where we can do samlResponse -> user profile conversion (still using the boxyhq/saml-jackson pkg) and the flow would be done, we have the user's data and can redirect the user. It does not seem like wrapping it with oauth2 provides anything? What am i missing here?
c
You aren't missing anything, it was an intentional design choice to layer OAuth2 over SAML because the integration would then mean it is just a virtual OAuth2 provider and you don't have to mess around with SAML directly. The embedded npm is a convenience that came after but retains the wrapper. We'll gladly accept PR if you can simplify this for the npm πŸ™‚
The service uses the npm so you will need to ensure it supports the current wrapper, you could introduce a new method in the controller to directly give you the profile
f
I see i see. Will see how much this bothers us and decide if we would prefer to change it πŸ˜…. I had another question, if you're running the ory/polis service publicly at eg
<http://enterprise-sso.myapp.com|enterprise-sso.myapp.com>
such that IDPs can post to it, then that would mean the admin interface is also accessible at that url. Is it possible to run polis with eg the api on one port and the admin interface on another? I understand you can add authentication to the admin interface. But i think it makes more sense for it to not be publicly available at all.
πŸ‘ 1
c
You would want an identity and access proxy in front, like Oathkeeper
f
Hi @creamy-art-71586. Ive found another peculiarity with using saml-jackson or ory polis. It does not seem possible to do idp initiated flows, because the oauthController.samlResponse function does not return the tenant or idp provider entityId or anything that can be used to identify the correct SAML connection, and this is required to exchange the code for an accessToken.
we do this in the service provider initiated flow, how can you find the right connection without the tenant in the IDP initiated flow
c
idp initiated login is not a pure oauth2 flow so you can just use
dummy
for client id and secret
f
Hmmmm, but it is necessary to do what we do for the SP initiated login?
c
Yes you get a code which needs to be exchanged for a profile