🚀 Feature: Add Support for "end_session_endpoint" or Custom URL for Logging Out #381

Closed
opened 2025-10-08 00:06:05 +03:00 by OVERLORD · 12 comments
Owner

Originally created by @computrav on GitHub.

Feature description

I successfully got Pocket ID working with Grist (https://getgrist.com), however I'm not able to fully sign out of the application. When I try to sign out, it appears to sign me out of Grist, but if I sign in again immediately from there, it authenticates against Pocket ID and auto-logs me in, since I'm still signed in with Pocket ID. Grist supports calling a "end_session_endpoint", but one is not configured for Pocket ID. I tried manually providing it as https://<domain where I'm running Pocket Id>/api/webauthn/logout -- which is where the Pocket Id UI POSTs to to logout, but it didn't work (I didn't expect it to, but tried anyhow).

I believe that if Pocket ID were to implement the end_session_endpoint or some other endpoint to logout, it would solve this issue. Is this something that can be implemented?

PS -- for anyone else trying to get Pocket Id OIDC working with Grist, here's the basics:

  1. In Pocket ID:
  • Go to "OIDC Clients" -> "Add OIDC Client"
  • Enter a name and for "Callback URLs" enter: https://<Grist Host>/oauth2/callback
  • Save the new OIDC Client
  1. In Grist (Docker/Docker Compose/etc), set these environment variables:
GRIST_OIDC_IDP_ISSUER="https://<Pocket ID Host>/.well-known/openid-configuration"
GRIST_OIDC_IDP_CLIENT_ID="<Client ID from the OIDC Client created in Pocket ID>"
GRIST_OIDC_IDP_CLIENT_SECRET="<Client Secret from the OIDC Client created in Pocket ID>"
GRIST_OIDC_SP_HOST="https://<Grist Host>"
GRIST_OIDC_IDP_SCOPES="openid email profile"  # Default
GRIST_OIDC_IDP_SKIP_END_SESSION_ENDPOINT=true  # Default=false, needs to be true for Pocket Id b/c end_session_endpoint is not implemented
GRIST_OIDC_IDP_END_SESSION_ENDPOINT="https://<Pocket ID Host>/api/webauthn/logout" # Only set this if GRIST_OIDC_IDP_SKIP_END_SESSION_ENDPOINT=false and you need to define a custom endpoint
  1. Also ensure that the GRIST_DEFAULT_EMAIL env variable is set to the same email address as your User profile within Pocket ID
  2. Start/Restart Grist

Pitch

So that logging out from apps can optionally trigger a logout from Pocket ID.

Originally created by @computrav on GitHub. ### Feature description I successfully got Pocket ID working with Grist (https://getgrist.com), however I'm not able to fully sign out of the application. When I try to sign out, it appears to sign me out of Grist, but if I sign in again immediately from there, it authenticates against Pocket ID and auto-logs me in, since I'm still signed in with Pocket ID. Grist supports calling a "end_session_endpoint", but one is not configured for Pocket ID. I tried manually providing it as https://<domain where I'm running Pocket Id>/api/webauthn/logout -- which is where the Pocket Id UI POSTs to to logout, but it didn't work (I didn't expect it to, but tried anyhow). I believe that if Pocket ID were to implement the `end_session_endpoint` or some other endpoint to logout, it would solve this issue. Is this something that can be implemented? **PS -- for anyone else trying to get Pocket Id OIDC working with Grist, here's the basics:** 1. In Pocket ID: - Go to "OIDC Clients" -> "Add OIDC Client" - Enter a name and for "Callback URLs" enter: `https://<Grist Host>/oauth2/callback` - Save the new OIDC Client 2. In Grist (Docker/Docker Compose/etc), set these environment variables: ``` GRIST_OIDC_IDP_ISSUER="https://<Pocket ID Host>/.well-known/openid-configuration" GRIST_OIDC_IDP_CLIENT_ID="<Client ID from the OIDC Client created in Pocket ID>" GRIST_OIDC_IDP_CLIENT_SECRET="<Client Secret from the OIDC Client created in Pocket ID>" GRIST_OIDC_SP_HOST="https://<Grist Host>" GRIST_OIDC_IDP_SCOPES="openid email profile" # Default GRIST_OIDC_IDP_SKIP_END_SESSION_ENDPOINT=true # Default=false, needs to be true for Pocket Id b/c end_session_endpoint is not implemented GRIST_OIDC_IDP_END_SESSION_ENDPOINT="https://<Pocket ID Host>/api/webauthn/logout" # Only set this if GRIST_OIDC_IDP_SKIP_END_SESSION_ENDPOINT=false and you need to define a custom endpoint ``` 3. Also ensure that the `GRIST_DEFAULT_EMAIL` env variable is set to the same email address as your User profile within Pocket ID 4. Start/Restart Grist ### Pitch So that logging out from apps can optionally trigger a logout from Pocket ID.
OVERLORD added the feature label 2025-10-08 00:06:05 +03:00
Author
Owner

@truncsphere commented on GitHub:

Adding my support for this. Lubelogger requires a logout URL for my OIDC provider if I disable password login.

@truncsphere commented on GitHub: Adding my support for this. Lubelogger requires a logout URL for my OIDC provider if I disable password login.
Author
Owner

@stonith404 commented on GitHub:

I've implemented the end session endpoint. Would you mind to test the ghcr.io/pocket-id/pocket-id:development image and let me know if everything works as expected?

Make sure to add a "Logout Callback URL" first, if your client provides this endpoint:

Image

Please also let me know if you see the following confirmation page or if you get redirected back to the client directly:

Image

@stonith404 commented on GitHub: I've implemented the end session endpoint. Would you mind to test the `ghcr.io/pocket-id/pocket-id:development` image and let me know if everything works as expected? Make sure to add a "Logout Callback URL" first, if your client provides this endpoint: ![Image](https://github.com/user-attachments/assets/3b0be1dc-9b6f-4bde-84f8-658d259dab1f) Please also let me know if you see the following confirmation page or if you get redirected back to the client directly: ![Image](https://github.com/user-attachments/assets/17d9f885-44a8-4980-b8d2-e88fa208ed3f)
Author
Owner

@cirrusflyer commented on GitHub:

+1

@cirrusflyer commented on GitHub: +1
Author
Owner

@etcg commented on GitHub:

I support this. I use Pingvin Share with Pocket ID, and if you disable password login and the start page in Pingvin, trying to log out immediately logs you back in. It’s basically the same issue (which seems to be fixed for other OIDC providers) described here: https://github.com/stonith404/pingvin-share/issues/598

@etcg commented on GitHub: I support this. I use Pingvin Share with Pocket ID, and if you disable password login and the start page in Pingvin, trying to log out immediately logs you back in. It’s basically the same issue (which seems to be fixed for other OIDC providers) described here: [https://github.com/stonith404/pingvin-share/issues/598](url)
Author
Owner

@kmendell commented on GitHub:

@stonith404 I tested this, i did end up getting the Logout page, and then after which i got redirected to the Pocket ID Login screen. I did not set and logout call back urls, and the app i used to test did not rpovide them.

One thing ill note as well, we will need to add the /api/oidc/end-session string to the OIDC Client UI along with all the other urls, unless i just missed it when i was testing.

@kmendell commented on GitHub: @stonith404 I tested this, i did end up getting the Logout page, and then after which i got redirected to the Pocket ID Login screen. I did not set and logout call back urls, and the app i used to test did not rpovide them. One thing ill note as well, we will need to add the /api/oidc/end-session string to the OIDC Client UI along with all the other urls, unless i just missed it when i was testing.
Author
Owner

@stonith404 commented on GitHub:

@kmendell Oh yeah, I forgot to add the link to the OIDC client page, thanks.

Which OIDC client did you use for testing?

@stonith404 commented on GitHub: @kmendell Oh yeah, I forgot to add the link to the OIDC client page, thanks. Which OIDC client did you use for testing?
Author
Owner

@kmendell commented on GitHub:

@stonith404 I used Portainer, as thats the only one i knew for a fact had a Logout Endpoint i could configure.

@kmendell commented on GitHub: @stonith404 I used Portainer, as thats the only one i knew for a fact had a Logout Endpoint i could configure.
Author
Owner

@stonith404 commented on GitHub:

Thanks @etcg. This was actually an issue of Pingvin Share but it should be fixed in the latest version. Sorry I should have mentioned that you have to rollback the migration before downgrading.

@stonith404 commented on GitHub: Thanks @etcg. This was actually an issue of Pingvin Share but it should be fixed in the latest version. Sorry I should have mentioned that you have to rollback the migration before downgrading.
Author
Owner

@stonith404 commented on GitHub:

@kmendell Alright thanks. It seems like Portainer doesn't ship the id_token_hint parameter to Pocket ID so it's expected that the logout page is shown.

@computrav, @truncsphere, @etcg and @cirrusflyer would you mind to test the development image with your services?

@stonith404 commented on GitHub: @kmendell Alright thanks. It seems like Portainer doesn't ship the `id_token_hint` parameter to Pocket ID so it's expected that the logout page is shown. @computrav, @truncsphere, @etcg and @cirrusflyer would you mind to test the development image with your services?
Author
Owner

@etcg commented on GitHub:

I tested it with Pingvin Share, and I don’t think it works for me. My callback URL is: https://share.domain.com/api/oauth/callback/oidc. I haven’t set a logout callback URL. In Pingvin Share, I have the start page and password login disabled.

However, I encountered a new bug in the development version: When I am logged out of Pocket ID (subdomain: sso.domain.com) and try to access my Pingvin Share (subdomain: share.domain.com), I get redirected to the Pocket ID login as expected. After authorization, however, it does not redirect back to Pingvin Share; instead, it opens the Pocket ID account page. I can only access Pingvin Share by manually reopening it after logging into Pocket ID. The same with another service, no redirect back to the service.

EDIT: I can't downgrade back to the latest version. I get this error on the Pocket ID page: Something went wrong. A critical error occured. Please contact your administrator.

Logs:

{"level":"error","ts":1739495375.5140955,"logger":"http.log.error","msg":"dial tcp [::1]:8080: connect: connection refused","request":{"remote_ip":"192.168.70.6","remote_port":"56500","client_ip":"192.168.70.6","proto":"HTTP/1.1","method":"GET","host":"192.168.70.6","uri":"/api/users/me","headers":{"Authorization":["REDACTED"],"User-Agent":["axios/1.7.9"],"Accept-Encoding":["gzip, compress, deflate, br"],"Connection":["keep-alive"],"Accept":["application/json, text/plain, */*"]}},"duration":0.001502684,"status":502,"err_id":"estcu0x3h","err_trace":"reverseproxy.statusError (reverseproxy.go:1269)"}
{"level":"error","ts":1739495375.514383,"logger":"http.log.error","msg":"dial tcp [::1]:8080: connect: connection refused","request":{"remote_ip":"192.168.70.6","remote_port":"56508","client_ip":"192.168.70.6","proto":"HTTP/1.1","method":"GET","host":"192.168.70.6","uri":"/api/users/me","headers":{"Connection":["keep-alive"],"Accept":["application/json, text/plain, */*"],"Authorization":["REDACTED"],"User-Agent":["axios/1.7.9"],"Accept-Encoding":["gzip, compress, deflate, br"]}},"duration":0.001230943,"status":502,"err_id":"dmpusjs07","err_trace":"reverseproxy.statusError (reverseproxy.go:1269)"}
{"level":"error","ts":1739495375.5209036,"logger":"http.log.error","msg":"dial tcp [::1]:8080: connect: connection refused","request":{"remote_ip":"192.168.70.6","remote_port":"56500","client_ip":"192.168.70.6","proto":"HTTP/1.1","method":"GET","host":"192.168.70.6","uri":"/api/application-configuration","headers":{"Authorization":["REDACTED"],"User-Agent":["axios/1.7.9"],"Accept-Encoding":["gzip, compress, deflate, br"],"Connection":["keep-alive"],"Accept":["application/json, text/plain, */*"]}},"duration":0.001151525,"status":502,"err_id":"rxrzvkrvn","err_trace":"reverseproxy.statusError (reverseproxy.go:1269)"}
Failed to get application configuration: Request failed with status code 502
Axios error: /api/users/me - Request failed with status code 502

EDIT 2: I restored the pocket-id.db from backup and it works again with the latest image.

@etcg commented on GitHub: I tested it with Pingvin Share, and I don’t think it works for me. My callback URL is: https://share.domain.com/api/oauth/callback/oidc. I haven’t set a logout callback URL. In Pingvin Share, I have the start page and password login disabled. However, I encountered a new bug in the development version: When I am logged out of Pocket ID (subdomain: sso.domain.com) and try to access my Pingvin Share (subdomain: share.domain.com), I get redirected to the Pocket ID login as expected. After authorization, however, it does not redirect back to Pingvin Share; instead, it opens the Pocket ID account page. I can only access Pingvin Share by manually reopening it after logging into Pocket ID. The same with another service, no redirect back to the service. EDIT: I can't downgrade back to the latest version. I get this error on the Pocket ID page: Something went wrong. A critical error occured. Please contact your administrator. Logs: ``` {"level":"error","ts":1739495375.5140955,"logger":"http.log.error","msg":"dial tcp [::1]:8080: connect: connection refused","request":{"remote_ip":"192.168.70.6","remote_port":"56500","client_ip":"192.168.70.6","proto":"HTTP/1.1","method":"GET","host":"192.168.70.6","uri":"/api/users/me","headers":{"Authorization":["REDACTED"],"User-Agent":["axios/1.7.9"],"Accept-Encoding":["gzip, compress, deflate, br"],"Connection":["keep-alive"],"Accept":["application/json, text/plain, */*"]}},"duration":0.001502684,"status":502,"err_id":"estcu0x3h","err_trace":"reverseproxy.statusError (reverseproxy.go:1269)"} {"level":"error","ts":1739495375.514383,"logger":"http.log.error","msg":"dial tcp [::1]:8080: connect: connection refused","request":{"remote_ip":"192.168.70.6","remote_port":"56508","client_ip":"192.168.70.6","proto":"HTTP/1.1","method":"GET","host":"192.168.70.6","uri":"/api/users/me","headers":{"Connection":["keep-alive"],"Accept":["application/json, text/plain, */*"],"Authorization":["REDACTED"],"User-Agent":["axios/1.7.9"],"Accept-Encoding":["gzip, compress, deflate, br"]}},"duration":0.001230943,"status":502,"err_id":"dmpusjs07","err_trace":"reverseproxy.statusError (reverseproxy.go:1269)"} {"level":"error","ts":1739495375.5209036,"logger":"http.log.error","msg":"dial tcp [::1]:8080: connect: connection refused","request":{"remote_ip":"192.168.70.6","remote_port":"56500","client_ip":"192.168.70.6","proto":"HTTP/1.1","method":"GET","host":"192.168.70.6","uri":"/api/application-configuration","headers":{"Authorization":["REDACTED"],"User-Agent":["axios/1.7.9"],"Accept-Encoding":["gzip, compress, deflate, br"],"Connection":["keep-alive"],"Accept":["application/json, text/plain, */*"]}},"duration":0.001151525,"status":502,"err_id":"rxrzvkrvn","err_trace":"reverseproxy.statusError (reverseproxy.go:1269)"} Failed to get application configuration: Request failed with status code 502 Axios error: /api/users/me - Request failed with status code 502 ``` EDIT 2: I restored the pocket-id.db from backup and it works again with the latest image.
Author
Owner

@computrav commented on GitHub:

Hi everyone -- apologies for not getting a chance to test this before it was pushed out.

Nonetheless, I've just tested it with Grist, and it works great! When I went to sign out of Grist, it brought me to Pocket ID as expected, and asked me to confirm the sign-out. I don't know if that is "standard" OIDC behavior, but I liked the option to kind of cancel the sign-out. Once I clicked to confirm the sign out, I confirmed that I was indeed signed out of Grist as well.

Grist-Specific OIDC Configuration Notes:

  • Grist has a GRIST_OIDC_IDP_END_SESSION_ENDPOINT environment variable. This is optional. I found that this did NOT need to be defined. I assume therefore that Grist is getting it from the Pocket ID /openid-configuration endpoint which is great.
@computrav commented on GitHub: Hi everyone -- apologies for not getting a chance to test this before it was pushed out. Nonetheless, I've just tested it with Grist, and it works great! When I went to sign out of Grist, it brought me to Pocket ID as expected, and asked me to confirm the sign-out. I don't know if that is "standard" OIDC behavior, but I liked the option to kind of cancel the sign-out. Once I clicked to confirm the sign out, I confirmed that I was indeed signed out of Grist as well. **Grist-Specific OIDC Configuration Notes:** - Grist has a `GRIST_OIDC_IDP_END_SESSION_ENDPOINT` environment variable. This is optional. I found that this did NOT need to be defined. I assume therefore that Grist is getting it from the Pocket ID /openid-configuration endpoint which is great.
Author
Owner

@stonith404 commented on GitHub:

Released in v0.33.0.

@stonith404 commented on GitHub: Released in `v0.33.0`.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/pocket-id-pocket-id-1#381