Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Returning to correct room after authentication #105

Closed
DanielMalmgren opened this issue Jun 1, 2022 · 59 comments
Closed

Returning to correct room after authentication #105

DanielMalmgren opened this issue Jun 1, 2022 · 59 comments

Comments

@DanielMalmgren
Copy link
Contributor

DanielMalmgren commented Jun 1, 2022

Hi.
After hours and hours of struggling (starting to feel like this guy) I think I almost have got oidc authentication working with Jitsi, but I'm stuck and hope to get some help here. I have got this far:

  1. When trying to enter a room I get redirected to my auth server
  2. I log in
  3. I'm sent back including the oidc code
    However, when I'm sent back I don't end up in the room I tried to enter but back on the main page. How is the flow supposed to work? Shouldn't jitsi after successful login do the redirection into the room?

Also I don't understand the TOKEN_AUTH_URL parameter. To get it working this far I have set it to the following:
https://idp.redacted/https/api/rest/v3.0/oauth/authorize?client_id=qG4ZETXFGdc4Nj33ACW6&response_type=code&redirect_uri=https%3A%2F%2Fvideo.redacted&scope=openid
...but from the example on the readme I guess I should put the room somewhere here and I don't understand where and how. Is the auth server supposed to do something with the room name and return it to Jitsi so that it knows which room to enter?

@MarcelCoding
Copy link
Owner

MarcelCoding commented Jun 1, 2022

TOKEN_AUTH_URL is the url that jitsi should redirect someone to try to login, {room} will be replaced with the actual room. https://auth.meet.example.com/room/{room} is the URL of this project, not your idp. Jitsi-openid does the actual authentication with your idp and generates a jwt that can be later verified by jitsi using the secret that both know.

@DanielMalmgren
Copy link
Contributor Author

Thanks for a very quick answer! I still don't follow though, what do you mean by "the URL of this project"? Is that (auth.meet.example.com in your example) supposed to point directly to jitsi-openid (the site answering on port 3000)?

@MarcelCoding
Copy link
Owner

MarcelCoding commented Jun 1, 2022

yes, of course with a reverse proxy -> in the end the port should be 443

@DanielMalmgren
Copy link
Contributor Author

Ah, then things are getting clearer! I think this could be explained a bit clearer in the readme... Just so that I'm clear now:

  1. The TOKEN_AUTH_URL in Jitsis .env points to jitsi-openid (answering on http on 3000 but put behind a tls proxy)
  2. Jitsi-openid is configured to call the authorize url at the auth server with redirect_uri set to the Jitsi site
  3. The auth server authenticates the user and redirects back to Jitsi including the oidc jwt

I'm still not really following how Jitsi is supposed to know which room to put the user in when it's returned from the auth flow?
Definitely too tired to continue with this today, but I'll continue tomorrow...

@MarcelCoding
Copy link
Owner

MarcelCoding commented Jun 1, 2022

the redirect url also has to be jitsi-openid (answering on http on 3000 but put behind a tls proxy) :) the room is in the redirect uri and stuff...

@MarcelCoding
Copy link
Owner

The redirect uri should be everything from jitsi opened (every path)

@DanielMalmgren
Copy link
Contributor Author

Ok! With your help I'm slowly getting there :-)

I am now (after enabling the implicit flow and adding scopes named "profil" and "email") getting my idp to accept the incoming authorization request and return a callback call to jitsi-openid. However, jitsi-openid doesn't seem to like the answer.

After logging in, the user is now redirected to https://my_jitsi_openid_url/callback#state=eyJyZXR1cm5UbyI6Ii8ifQ&token_type=Bearer which seems correct to me. But jitsi-openid just says "Bad Request" and in the Docker log I get the following:

jitsi-openid_1 | BadRequestError: state missing from the response
jitsi-openid_1 | at /app/index.js:2:147615
jitsi-openid_1 | at processTicksAndRejections (node:internal/process/task_queues:96:5)

Any idea what's happening?

@MarcelCoding
Copy link
Owner

MarcelCoding commented Jun 2, 2022

Sorry for the things with the scopes. I only teste it with keycloak and these are there allowed by default. Jitsi openid generates a state witch is then sound be added to the redirect uri by the idp. https://stackoverflow.com/a/26132537
In your case jitsi openid complains that your idp isn't appending the state to the redirect uri.

@DanielMalmgren
Copy link
Contributor Author

Yes, but if you look at the url it's redirecting back to, there is a state there, that's why I don't really understand the error...

@DanielMalmgren
Copy link
Contributor Author

Hi again.
After some more testing it seems that jitsi-openid actually sees the state if I replace the hash sign with a question mark (ie https://my_jitsi_openid_url/callback?state=eyJyZXR1cm5UbyI6Ii8ifQ&token_type=Bearer instead of https://my_jitsi_openid_url/callback#state=eyJyZXR1cm5UbyI6Ii8ifQ&token_type=Bearer) which is very strange since the correct way of sending it (and the only way using my idp software) when using the implicit flow is as a fragment, so it should be a hash. I don't know if this is something that Keycloak does differently using some non standard way?

I don't know, this is maybe starting to be a question worth asking at the express-openid-connect project instead?

@MarcelCoding
Copy link
Owner

The fragment is because of the implicit flow -> the fragment isn't send to the server and implicit flow means that the response is handled client side, witch wouldn't work for this use case. Why do you need the implicit flow?

@DanielMalmgren
Copy link
Contributor Author

Hmmm... No, I don't actually need the implicit flow, I just got the impression that's what is used. Now I realize though that it actually says response_type=id_token. Seems the problem is that my idp for some strange reason thinks it IS implicit flow. I guess I'll have to check with the support for our idp software. But shouldn't the state be sent as fragment also when response_type is id_token?

@MarcelCoding
Copy link
Owner

No because it is interpreter by the backend and fragents are not passed to the backend

@DanielMalmgren
Copy link
Contributor Author

Good point. According to the specs it should be in a fragment though and in my idp it's not configurable. I don't know how it's handled in other systems, is it the frontend page's work to send it on to the backend in some way?

The only solution I can see right now is to build my own intermediate callback page that uses JS to convert the url (replacing the # with ?) and then passing it on to the "real" callback. Seems like a workaround more than a solution though :-/

@DanielMalmgren
Copy link
Contributor Author

Ok, after some more reading I think I found the culprit. jitsi-openid sends response_mode=form_post which means the idp should post the result as a form post. My idp totally seems to ignore response_mode so I guess the problem lies there :-/

@MarcelCoding
Copy link
Owner

MarcelCoding commented Jun 2, 2022

Ok, I found an option in the underlying liberty to change the response mode.

Unfortunately, I currently don't have direct access to a jitsi using this script. I asked one of my friends, idk when he will respond.
If you want you could try it yourself or otherwise you probably have to wait until tomorrow, for me to test it and create a release.

I added a new env variable: RESPONSE_MODE, see https://github.com/MarcelCoding/jitsi-openid#docker-compose

I pushed it in master, the docker image is available over the tag edge.
Andt the index.js: https://envs.sh/QDR.js directly. - I can't upload a js file here directly, I know it seems a bit sketchy. :)

@DanielMalmgren
Copy link
Contributor Author

Thanks, that's appreciated! I don't think it will help in my case though since it seems my idp actually completely is ignoring the response_mode. So my current theory is the problem was at that side all the time, I'm in contact with the support to get a solution.

@MarcelCoding
Copy link
Owner

MarcelCoding commented Jun 2, 2022

Ohh, I thought it refused to accept a response mode of form post. I just tested it and it didn't work, the library only accepts form_post

@DanielMalmgren
Copy link
Contributor Author

DanielMalmgren commented Jun 9, 2022

Hi, it's me again. I've come a little further now, but still not really there... First my idp redirected to https://redacted_name.se/callback#state=eyJyZXR1cm5UbyI6Ii8ifQ&token_type=Bearer and then I got this in my log:

jitsi-openid_1 | BadRequestError: state missing from the response
jitsi-openid_1 | at /app/index.js:2:147615
jitsi-openid_1 | at processTicksAndRejections (node:internal/process/task_queues:96:5)

Now I have fixed a rewriting of the url from # to ? so the idp instead redirects to https://redacted_name.se/callback?state=eyJyZXR1cm5UbyI6Ii8ifQ&token_type=Bearer so the state reaches jitsi-openid, but now instead it says this in the log:

jitsi-openid_1 | BadRequestError: checks.state argument is missing
jitsi-openid_1 | at /app/index.js:2:147615
jitsi-openid_1 | at processTicksAndRejections (node:internal/process/task_queues:96:5)

So obviously something changed, but it still doesn't like it. Any idea what goes wrong now?

edit: Actually, after reading a bit (here) I think the problem might be a cookie getting lost somewhere down the road. I'll continue investigating...

@DanielMalmgren
Copy link
Contributor Author

DanielMalmgren commented Jun 14, 2022

Ok. Now I'm stuck on the last redirect, hope you can help me see what's going wrong...

After logging in I'm now stuck in a never ending loop:

  1. My idp redirects to https://my_jitsi_openid_url/callback?state=eyJyZXR1cm5UbyI6Ii8ifQ&token_type=Bearer which should be fine, right?
  2. If I understand things correctly, what jitsi-openid should do now is redirecting back to my jitsi site including the owt, but what it does is redirecting (http 302) to /room/room_name (room_name being the name of the room I'm trying to access) which is the exact same URL I was on before logging in.
  3. I'm now redirected back to my idp.

While this loop is happening I can actually see my camera picture in the browser so I think I'm logged into the room and the redirect loop seems to happen in the background. After a few seconds though I'm thrown to a "too many redirects" error page instead.

Any idea what could cause this behaviour?

@MarcelCoding
Copy link
Owner

If you can see your camera, that must mean you are going over jitsi direct?

@MarcelCoding
Copy link
Owner

MarcelCoding commented Jun 14, 2022

I think the openid connect implementation that I use only supports id_token, maybe I should switch the implementation. I am going to rewrite this in rust and use this implementation, it seems that it supports that code authentication that we need: https://github.com/ramosbugs/oauth2-rs (then it is only oauth2 and not opened connect -> the is no autodiscovery)

GitHub
Extensible, strongly-typed Rust OAuth2 client library - GitHub - ramosbugs/oauth2-rs: Extensible, strongly-typed Rust OAuth2 client library

@MarcelCoding
Copy link
Owner

MarcelCoding commented Jun 14, 2022

Could you maybe provide me with the name of your IDP, so that I could test if it works, or is it some kind of paid enterprise software? Currently, I (can) only test with keycloak.

@DanielMalmgren
Copy link
Contributor Author

Yep, it's a paid enterprise solution (this one) so I don't think there's any easy way for you to test it. I could give you an url and a test account to the test environment so you could see the behaviour yourself but I guess it wouldn't be meaningfull without shell access to the server and that would be harder to fix.

But it should work the way I have set it up now right? So that when the callback endpoint gets a request with a state and the correct cookies should make jitsi-openid construct a correct jwt and send it on to Jitsi? I don't really see why it would then redirect back to it's own room endpoint like it does now. Could it make any difference that the state now is sent as an url query even though it should be as form post? Also, is there any way to increase the debugging to see more of what is happening?

@MarcelCoding
Copy link
Owner

I think the express implementation only supports id tokens, the rust version would use the state stuff. Yes now it should work. The redirect currently happens because express could'nd find The Id toke n.

@DanielMalmgren
Copy link
Contributor Author

Ok, but where does it look for the id token? If I understand things correctly what is supposed to happen now is that it calls the token endpoint on my idp to get the id token, I'm not really sure if that is happening?

@MarcelCoding
Copy link
Owner

Yes, but the express implementation directly asks for an id token in the auth URL as a response. Your idp is ignoring this/not supporting this and is sending a code.

@MarcelCoding
Copy link
Owner

I did a rewrite witch uses a different implementation with way more capabilities. Could you may try it out. The docker image uses the tag edge and the binary directly can be downloaded here https://github.com/MarcelCoding/jitsi-openid/actions/runs/2520856815 (artifacts). All the environment variables are either the same or backward compatible.

@DanielMalmgren
Copy link
Contributor Author

Great news! I'm strongly suspecting my idp software is the big problem for me (still waiting for their support to confirm my problems) but everything I can do to work around it is appreciated!

This new version does not seem to like my ISSUER_BASE_URL though, it's quite long. When starting the container I get this:

jitsi-openid_1 | 2022-06-20T07:02:28.325620Z INFO jitsi_openid: Using identity provider: https://idp.my_domain.se/https/api/rest/v3.0/oauth/qG4ZETXFGdc4Nj33ACW6 and client-id: qG4ZETXFGdc4Nj33ACW6
jitsi-openid_1 | Error: Validation error: unexpected issuer URI https://idp.my_domain.se/ (expected https://idp.my_domain.se/https/api/rest/v3.0/oauth/qG4ZETXFGdc4Nj33ACW6)

The json with my openid-configuration is reachable at https://idp.my_domain.se/https/api/rest/v3.0/oauth/qG4ZETXFGdc4Nj33ACW6/.well-known/openid-configuration.

@MarcelCoding
Copy link
Owner

MarcelCoding commented Jun 20, 2022

I know... This implementation (an maybe even the openid connect spec is expecting the issuer URL to be the same as provided as the environment variable for ISSUER_BASE_URL)

I already created an issue, while I encountered the same issue.
ramosbugs/openidconnect-rs#75

A temporary workaround would be to fork the implementation and disable this check.

Is your openid connect discovery also available at https://idp.my_domain.se/.well-known/openid-configuration?

@MarcelCoding
Copy link
Owner

Ok, then I am going to create a temporally fork of the underlying implementation until they responded to my issue.

@MarcelCoding
Copy link
Owner

MarcelCoding commented Jun 20, 2022

Cloud you try it again, I just verified that it worked for my setup. (described here ramosbugs/openidconnect-rs#75)

@DanielMalmgren
Copy link
Contributor Author

Yep, now it starts as intented! And now I get a very clear error message about missing id token. You have clearly convinced me that the problem lies within my idp, either a bug or a misconfiguration. I'll report back when I have more information!

@MarcelCoding
Copy link
Owner

MarcelCoding commented Jun 21, 2022

The problem with that is that the id token is not mandatory according to the spec. You may have an option to enable it on the admin interface. I also could implement an additional call to the user info endpoint.
Until 20 o'clock I don't have relay time today. You might be able to try it again tomorrow. :)

@MarcelCoding
Copy link
Owner

Could you try it again, I added user info and verified that it is working for keylcoak. (If I force disable the id token.)

@DanielMalmgren
Copy link
Contributor Author

Wow!!! I think that actually worked! I'm not really sure what you changed, but now it I was sent on to Jitsi with a jwt including my username, just like magic!

@DanielMalmgren
Copy link
Contributor Author

I think I have another (maybe last) question: Is there any way to get it to send more user information in the jwt? Currently it sends this user info:

"user": {
"id": "damal08",
"email": null,
"name": null,
"avatar": null
}

(where damal08 is my username)
...but it would be very nice if it would also pass my name and email on in the jwt. Is that possible?

@MarcelCoding
Copy link
Owner

I assume that the basic authentication process is not working. 🎉 Theraticly this information is being passed: https://github.com/MarcelCoding/jitsi-openid/blob/main/src/main.rs#L298-L307 At least for keycloak it is working. It could be that either your IDP doesn't provide this information or has different properties' names. I could implement it for you if you provide me with an example of your user info endpoint response. (or is there public documentation, I could find any)

@DanielMalmgren
Copy link
Contributor Author

Ah! Well, with that info it was a piece of cake, I only needed to include attributes named "name" and "email" in the Oauth2 info from my idp, so now I get my name in the meeting! Now if I could just tell Jitsi to prohibit the user from changing that name before going into the room...

@MarcelCoding
Copy link
Owner

@DanielMalmgren
Copy link
Contributor Author

Yep, I'm already on it :-D

Thanks a lot for your hard work on this, I realize you've gon lengths to help me. Can I do anything to compansate you?

@MarcelCoding
Copy link
Owner

You really don't have to do anything, it's currently just a hobby. I am just a student :D I am going to leave this issue open until ramosbugs/openidconnect-rs#75 is finished. After that, I am also going to create a new release.

@DanielMalmgren
Copy link
Contributor Author

DanielMalmgren commented Jun 28, 2022

Hi again. I've got a new problem, but I thought I'd handle it here as well, since I'm using the edge version discussed above in this issue.

My problem now is the expire date of the jwt. I'm not really sure how it's calculated, but when I'm trying now I get jwt's which expired almost a week ago which makes Jitsi not accept them. When I try in an incognito tab everything works fine so it seems it has something with my browsers session to do, could it be that the exp date was set when I tried around with this last week and then isn't updated correctly?

edit: After some more testing, it seems this only happen if I in the list of meetings click a meeting that was created last week. Joining meetings created today works fine. Could it be that the exp date is based on when the meeting was created?

edit 2: After even more digging I realize that the meetings in that list is saved as cookies in my browser and that the entire URL including the jwt is saved there, so it never asks jitsi-openid at all when clicking those links. So this is clearly not a problem with jitsi-openid but rather in Jitsi itself, someone obviously did a bit of a think tank here.

@MarcelCoding
Copy link
Owner

That's interesting because anytime I wasn't logged in into jitsi (expired or no jwt) there came a popup with a button "I am the host", where I got redirected to the login page.

@DanielMalmgren
Copy link
Contributor Author

That's weird. I guess there's som other setting affecting this?

I think I will simply go around the problem by disabling the list completely (RECENT_LIST_ENABLED=false), I have no real need for it anyway. Discussed it here.

@MarcelCoding
Copy link
Owner

MarcelCoding commented Jul 10, 2022

Hi, I am again. I just updated the description regarding jwts. I also implemented some logic for someone else. It should affect you, (I tested everything using keycloak) I just want to be sure that it also works for your IDP. (#122)

@DanielMalmgren
Copy link
Contributor Author

DanielMalmgren commented Aug 8, 2022

Hi.
Sorry for the late reply, I've been on a long vacation.

I tried now and I can't get it to work. Is this new option supposed to be optional? If I don't include the new option in my yml file the container doesn't start at all, it says "missing field acr_values" and if I include it I get the following when I try to enter a room:

An authentication context requirement is configured. To validate this requirement an id token is required ... no id token was provided

I also tried configuring my idp to send a static dummy value for acr, but I get the same error. (edit: I realize now though that this might not be sent in the id token so I guess it makes no difference. Seems simply my idp solution doesn't have support for acr so it would need to be optional)

@MarcelCoding
Copy link
Owner

MarcelCoding commented Aug 8, 2022

Sorry, my bad - I forgot to make the "acr_values" optional - If you specify acr_values an id token is required to validate them, if you don't specify any, the id token is optional. It should be working now - the build maybe take some time

1ef7808
https://github.com/MarcelCoding/jitsi-openid/actions/runs/2817213307

@DanielMalmgren
Copy link
Contributor Author

Yep, works like a charm now! Since my idp doesn't seem to have support for acr I can not test that particular function, but at least it works like before without it :-)

@MarcelCoding
Copy link
Owner

Unless you want to force users to use a specific authentication class - (force password, security key, ...) this isn't something that you want to use.

@DanielMalmgren
Copy link
Contributor Author

Yep. And I can simply choose which authentication methods in the idp is available for this oidc client, so there's no need for passing that information in the token.

What do you say, should we close this issue up? All my problems are solved now! Or should you make a release first?

@MarcelCoding
Copy link
Owner

And this is also fixed for you, that means I can switch back to the upstream version and do not need to use my fork anymore?

@DanielMalmgren
Copy link
Contributor Author

You're talking about the openidconnect-rs issuerurl issue now, right? Yes, I think that should be safe.

@MarcelCoding
Copy link
Owner

Ok, I am going to create a release.

@MarcelCoding
Copy link
Owner

@lazyzyf
Copy link

lazyzyf commented Feb 11, 2023

The redirect uri should be everything from jitsi opened (every path)

do you mean the redirect uir should be the same as the TOKEN_AUTH_URL?

@lazyzyf
Copy link

lazyzyf commented Feb 11, 2023

The redirect uri should be everything from jitsi opened (every path)

can you please give an example how to set redirect uris in authelia conifiguraiton file?

@MarcelCoding
Copy link
Owner

MarcelCoding commented Feb 12, 2023

https://keycloak.marcel.hel1.not4y.net/realms/main/.well-known/openid-configuration You have something like this for your provider. The issuer url is the part of the url up to .well-known -> <ISSUER_URL>/.well-known/openid-configuration.
You don't have to specify any other urls regarding your idp. If you have a look at the docs, this endpoint should be at the root of your domain: https://www.authelia.com/integration/openid-connect/introduction/#well-known-discovery-endpoints I am not familiar with authelia, I hope it helps you. The redirect url configured in your idp should be something like https://auth.meet.example.org/callback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants