OIDC with Discord not working properly #10

Open
opened 2024-05-12 22:04:42 +00:00 by mh84 · 8 comments
mh84 commented 2024-05-12 22:04:42 +00:00 (Migrated from gitlab.com)

Hi,

first at all thanks for your work.

While trying to port/rewrite one of my apps from yew to leptos i need to get single sign on with discord working again, but i encountered some problems:

  • it seems we cant load https://discord.com/.well-known/openid-configuration through missing CORS Header (ACCESS-CONTROL-ALLOW-ORIGIN) (explanation) (i worked around it adding an cors proxy: https://corsproxy.io)
  • this may be solvable by making it optional to provide an configuration alongside AuthParameters
  • but as mentioned in #8, Discord too doesn't provide an end_session_endpoint
  • this may be solvable by making it optional inside Configuration
  • using Discord as identity provider, one has to confirm every login, except requesting access with additional query parameters &prompt=none
  • this may be solvable by being able to provide optional query parameters alongside AuthParameters
  • and finally, the login still didn't work after aquiring the exchange code, and i'm kind of lost where to further invastigate why

I'm glad to help and contribute any further (and may even reach out to and if its possible to provide CORS headers) if someone guides me where to further investigate what part is not going into the correct direction.

Cheers, and thanks in advance!

Hi, first at all thanks for your work. While trying to port/rewrite one of my apps from yew to leptos i need to get single sign on with discord working again, but i encountered some problems: - it seems we cant load https://discord.com/.well-known/openid-configuration through missing CORS Header (ACCESS-CONTROL-ALLOW-ORIGIN) ([explanation](https://stackoverflow.com/questions/43262121/trying-to-use-fetch-and-pass-in-mode-no-cors)) (i worked around it adding an cors proxy: https://corsproxy.io) - this may be solvable by making it optional to provide an configuration alongside AuthParameters - but as mentioned in #8, Discord too doesn't provide an `end_session_endpoint` - this may be solvable by making it optional inside Configuration - using Discord as identity provider, one has to confirm every login, except requesting access with additional query parameters `&prompt=none` - this may be solvable by being able to provide optional query parameters alongside AuthParameters - and finally, the login still didn't work after aquiring the exchange code, and i'm kind of lost where to further invastigate why I'm glad to help and contribute any further (and may even reach out to and if its possible to provide CORS headers) if someone guides me where to further investigate what part is not going into the correct direction. Cheers, and thanks in advance!
kerkmann commented 2024-05-13 11:53:01 +00:00 (Migrated from gitlab.com)

Hi Marcel, first of all, thanks for reaching out. I've looked into the Discord Developer Docs and as far as I can tell, Discord only supports the authorization code flow with a client id and client secret. A public client should NEVER have such an secret in there. But what you could do is setting up your own OIDC Server (for example, Rauthy, Keycloak, GoAuthentik) and add Discord as Single Sign On provider. With that setup you would be able to add your client id and client secret to your own OIDC Backend and enable it there. 😄

Hit me if I am wrong, but I think Discord is not designed for public clients. I think that's also the reason why discord has no end_session_endpoint. :)

Hi Marcel, first of all, thanks for reaching out. I've looked into the [Discord Developer Docs](https://discord.com/developers/docs/topics/oauth2#authorization-code-grant) and as far as I can tell, Discord only supports the `authorization code` flow with a `client id` and `client secret`. A public client should NEVER have such an secret in there. But what you could do is setting up your own OIDC Server (for example, Rauthy, Keycloak, GoAuthentik) and add Discord as Single Sign On provider. With that setup you would be able to add your `client id` and `client secret` to your own OIDC Backend and enable it there. :smile: Hit me if I am wrong, but I think Discord is not designed for public clients. I think that's also the reason why discord has no `end_session_endpoint`. :)
kerkmann commented 2024-05-13 11:58:27 +00:00 (Migrated from gitlab.com)

btw; I think Discord is violating the RFC of OIDC. It should always contain the end_session_endpoint, based on the rfc.

To support OpenID Connect RP-Initiated Logout, the RP needs to obtain the RP-Initiated Logout related OP metadata. This OP metadata is normally obtained via the OP's Discovery response, as described in OpenID Connect Discovery 1.0 [OpenID.Discovery], or MAY be learned via other mechanisms.

This OpenID Provider Metadata parameter MUST be included in the Server's discovery responses when RP-Initiated Logout and Discovery are supported:
end_session_endpoint REQUIRED. URL at the OP to which an RP can perform a redirect to request that the End-User be logged out at the OP. This URL MUST use the https scheme and MAY contain port, path, and query parameter components.

btw; I think Discord is violating the RFC of OIDC. It should always contain the `end_session_endpoint`, based on the [rfc](https://openid.net/specs/openid-connect-rpinitiated-1_0.html#OPMetadata). > To support OpenID Connect RP-Initiated Logout, the RP needs to obtain the RP-Initiated Logout related OP metadata. This OP metadata is normally obtained via the OP's Discovery response, as described in OpenID Connect Discovery 1.0 [OpenID.Discovery], or MAY be learned via other mechanisms. > This OpenID Provider Metadata parameter MUST be included in the Server's discovery responses when RP-Initiated Logout and Discovery are supported: `end_session_endpoint` REQUIRED. URL at the OP to which an RP can perform a redirect to request that the End-User be logged out at the OP. This URL MUST use the https scheme and MAY contain port, path, and query parameter components.
mh84 commented 2024-05-13 12:19:29 +00:00 (Migrated from gitlab.com)

I guess you are wrong in this point.

See here: https://discord.com/developers/docs/topics/oauth2#authorization-code-grant-authorization-url-example -> there is no need for any client secret to be provided (and this way its perfectly fine working, i got returned the exchange code, but then nothing further seems to happen).

And https://discord.com/developers/docs/topics/oauth2#implicit-grant is working also totally fine with https://github.com/ctron/yew-oauth2 (but i havent tried Authorization Code Grant with that one.), so i guess discord is fine for authentication purposes for public clients.

I guess you are wrong in this point. See here: https://discord.com/developers/docs/topics/oauth2#authorization-code-grant-authorization-url-example -> there is no need for any client secret to be provided (and this way its perfectly fine working, i got returned the exchange code, but then nothing further seems to happen). And https://discord.com/developers/docs/topics/oauth2#implicit-grant is working also totally fine with https://github.com/ctron/yew-oauth2 (but i havent tried Authorization Code Grant with that one.), so i guess discord is fine for authentication purposes for public clients.
kerkmann commented 2024-05-13 14:56:37 +00:00 (Migrated from gitlab.com)

Oh! You are right, indeed Discord is also suitable for public clients. I'll take a deeper look into it and test stuff out (later). But still confusing why Discord has no end_session_endpoint. But that's something I need to figure out/maybe rethink about the current code structure.

Would be general better to destroy the session beforehand and then optionally use the end_session_endpoint, but that's something I need to rebuild. :D

I'll also add a builder pattern for the AuthParameters, to be more flexible. I hope the current state is not too bad, I'll try my best to fix it. :)

Oh! You are right, indeed Discord is also suitable for public clients. I'll take a deeper look into it and test stuff out (later). But still confusing why Discord has no `end_session_endpoint`. But that's something I need to figure out/maybe rethink about the current code structure. Would be general better to destroy the session beforehand and then optionally use the `end_session_endpoint`, but that's something I need to rebuild. :D I'll also add a builder pattern for the `AuthParameters`, to be more flexible. I hope the current state is not too bad, I'll try my best to fix it. :)
kerkmann commented 2024-05-13 14:58:24 +00:00 (Migrated from gitlab.com)

For the CORS stuff, there are some reqwest endpoints (I think two or three), where you could add the https://splittydev.github.io/spotify-rs/reqwest/header/enum.AccessControlAllowOrigin.html. This would of course be awesome if it's possible to add it through the AuthParameters. :D

But I can also add it, it's not such a big deal. :3

For the `CORS` stuff, there are some `reqwest` endpoints (I think two or three), where you could add the [https://splittydev.github.io/spotify-rs/reqwest/header/enum.AccessControlAllowOrigin.html](reqwest::header::AccessControlAllowOrigin). This would of course be awesome if it's possible to add it through the `AuthParameters`. :D But I can also add it, it's not such a big deal. :3
mh84 commented 2024-05-13 16:43:40 +00:00 (Migrated from gitlab.com)

That is nothing that can be done on client side, as this header must be provided from server side 😄

Discord (https://discord.com/.well-known/openid-configuration):
grafik

Some other (https://dev-qcuxgjrapycf5ib4.us.auth0.com/.well-known/openid-configuration):
grafik

I guess best would be to mention this somewhere in the docs, that the auth provider must be able to serve the openid-configuration (via https) with CORS headers set (access-control-allow-origin: *, but i'm not 100% sure if this is sufficent).

That is nothing that can be done on client side, as this header must be provided from server side :smile: Discord (https://discord.com/.well-known/openid-configuration): ![grafik](/uploads/115c861cd68b905521fe1a4cbed9387b/grafik.png) Some other (https://dev-qcuxgjrapycf5ib4.us.auth0.com/.well-known/openid-configuration): ![grafik](/uploads/d421120c3c811f05e877d5c026b29ff3/grafik.png) I guess best would be to mention this somewhere in the docs, that the auth provider must be able to serve the openid-configuration (via https) with CORS headers set (access-control-allow-origin: *, but i'm not 100% sure if this is sufficent).
mh84 commented 2024-05-13 16:54:00 +00:00 (Migrated from gitlab.com)

I found some further read about OIDC/OAuth2 about implicit grant vs authorization code and may Discord uses some mix / legacy state, who knows 🤷

https://developer.okta.com/blog/2018/05/24/what-is-the-oauth2-implicit-grant-type
https://developer.okta.com/blog/2019/05/01/is-the-oauth-implicit-flow-dead

I found some further read about OIDC/OAuth2 about implicit grant vs authorization code and may Discord uses some mix / legacy state, who knows :shrug: https://developer.okta.com/blog/2018/05/24/what-is-the-oauth2-implicit-grant-type https://developer.okta.com/blog/2019/05/01/is-the-oauth-implicit-flow-dead
kerkmann commented 2024-05-22 10:34:30 +00:00 (Migrated from gitlab.com)

jfyi; I was a little bit busy but I'll take some time in the next days to solve the issues. :)

jfyi; I was a little bit busy but I'll take some time in the next days to solve the issues. :)
Sign in to join this conversation.
No labels
WIP
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
kerkmann/leptos_oidc#10
No description provided.