Open alahiff opened 1 month ago
I think the better approach would be to split the auth in two parts instead (which is a very typical OIDC flow):
I did not try it yet, but my feeling that passing a valid token should already work, so the alternate clients just need to do the oidc-login themself ( there are suitable libs out there for most frameworks).
Otherwise we open up for referer-spoofing attacks.
Thanks for the reply. That's pretty much what I was planning to do, with a completely custom frontend. I just need to work out how to actually create the users in the backend in this case (i.e. so there are appropriate documents in the UserIdentity
collection).
I was also hoping it might be possible to run multiple instances of the official (unmodified) SciCat frontend instead as an option, but if not, that's not a problem.
You can configure multiple FE with a single BE. Each user working on the FE will get its own token.
Could you elaborate more on what you mean by "create users in the BE"?
I'm really curious to see a proof of concept of the solution that you two (@alahiff and @bpedersen2) mention in the post above
You can multiple FE with a single BE. Each user working on the FE will get its own token.
How do you do this? The backend has the configuration OIDC_SUCCESS_URL
, which means that after authentication via Keyclock users will always be redirected back to a single FE, rather than the FE they originally tried to login from. Maybe there's something simple I'm missing :-)
@alahiff my mistake. Apologies for the confusion. You are correct. I answered before I reviewed completely your and @bpedersen2 answers. We need some code refactoring before we can do that.
Could you elaborate more on what you mean by "create users in the BE"?
If the FE is integrated with Keycloak (rather than the BE) then after successful authentication the frontend could create a token which could then be provided when querying the backend. I was thinking that the BE wouldn't even need to be integrated with OIDC, but of course would need to know the same secret as the FE in order to validate the tokens. The existing JWT auth in the backend could be used.
Looking at an existing token created by the BE, it contains _id
and id
(identical values) which refer to an existing user in MongoDB. So the problem with the above is that somehow the FE needs to get the id of the user identity from the BE, and to trigger creation of a new identity when a user logs in for the first time.
I'm not sure if this could be done using the existing user API in the BE, or maybe the existing OIDC integration in the BE could somehow be leveraged, as it already handles creating the user identity: https://github.com/SciCatProject/scicat-backend-next/blob/1cd3af406897eb8d386722a52081dc462fbd4298/src/auth/strategies/oidc.strategy.ts#L125
No, that is not how oidc auth should be used.
The typical flow is:
I trust @bpedersen2 to provide the correct information. I think I need to go back and read once more the OIDC documentation.
@alahiff: just to make sure that I understand correctly what you are trying to achieve, can you confirm that my following statement is true:
You would like to be able to deploy a single backend and multiple frontends with different URLs. You would like to be able to authenticate through OIDC from any of the frontend and be able to be redirected back to the correct one.
Thanks
@nitrosx Yes, that statement is true.
@alahiff thanks for confirming. I will raise the question with the community at the next collaborators meeting, which is this afternoon.
On each request to the BE this token is passsed to the BE
The current tokens accepted by the backend look like this:
{
"_id": "66a248704e178fc76d15cd09",
"username": "oidc-user",
"email": "oidc-user@facility.com",
"authStrategy": "oidc",
"__v": 0,
"id": "66a248704e178fc76d15cd09",
"userId": "66a248704e178fc76d15cd09",
"iat": 1722945688,
"exp": 1722949288
}
How does the FE know the id in your step 2? (as it's something generated & stored in the backend).
I suppose one option is use in the tokens the ids from the OIDC provider instead, and modify the backend appropriately.
@alahiff I just chatted with the collaborators and @minottic pointed me to the following code: https://github.com/SciCatProject/scicat-backend-next/blob/master/src/auth/auth.controller.ts#L92-L95
According to this section of the code, the url that you are redirected to upon successful login is configured in the backend configuration under the oidc.successUrl
.
If you leave that entry empty, it will use the referrer
field that is present in the request header.
Let me know if this help and your feedback on how to improve the documentation
@nitrosx That was one of the first things I tried but it doesn't work unfortunately. After authentication with Keycloak referrer
is undefined and the backend gives this error:
[Nest] 1 - 08/01/2024, 12:40:05 PM ERROR "Internal server error"
[Nest] 1 - 08/01/2024, 12:40:05 PM ERROR TypeError [ERR_INVALID_URL]: Invalid URL
Thanks for confirming. I will inquire more with the collaborators that have done it in the past and let you know.<
Now I'm wondering how we can test this use case in CI/CD
the snippet that Max shared tries to get the referer from the BE callback, and, given what you say, the referer is empty there because kc intercepts it and unset it. This is because of the login flow:
FE --> BE (init) --> KC --> BE (callback) --> FE
Given that the referer is inspected in the BE (callback)
, its value is lost because of the KC step. What one can do, I think, is to inspect the referer in the BE (init)
instead and set it as the BE session FE successUrl
. I think this can be done by modifying this part of the code, probably the OidcAuthGuard
I agree @bpedersen2's flow is a better implementation of OIDC, closer to PKCE
Summary
We would like to have multiple frontends sharing a single backend, using Keycloak for authentication. Each frontend would be for a different experiment and require different configuration (hence the reason for multiple frontends).
Current Behaviour
I tried removing
OIDC_SUCCESS_URL
from the backend config since there can be multiple possible URLs, depending on the frontend being used. I was expecting the code introduced by https://github.com/SciCatProject/scicat-backend-next/pull/603 to ensure this works correctly, but the backend gives:Adding some
console.log
statements into the backend it seems thatrequest
ingetRequest
in https://github.com/SciCatProject/scicat-backend-next/blob/master/src/auth/guards/oidc.guard.ts does contain the correct value ofreferer
in the header. However, after authentication with Keycloak the backend setsreferer
toundefined
(inoidc.guard.ts
), so the information aboutreferer
obtained in the previous step was lost.Expected Behaviour
When
OIDC_SUCCESS_URL
is not defined in the backend config, after succesful authentication users would get redirected back to the frontend they had originally come from (due to thereferer
header).Details
I am using SciCatLive 2.8.0.