-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Description
Describe the bug
Typebot’s integration with Keycloak fails because the fields expected by the Typebot Account model do not fully match the standard OAuth/OpenID Connect token response provided by Keycloak.
Specifically, Typebot expects an expires_at field (representing an absolute timestamp) and a refresh_token_expires_in field, whereas Keycloak returns expires_in (a duration in seconds) and refresh_expires_in.
In addition, the presence of unrecognized fields (such as not-before-policy) completely blocks the login process, forcing developers to implement custom transformations to achieve compatibility.
To Reproduce
Steps to reproduce the behavior:
- Integrate Typebot authentication using Keycloak as the OpenID Connect provider.
- Notice the mismatched fields:
- Typebot expects
expires_at, but Keycloak returnsexpires_in(duration in seconds). - Typebot expects
refresh_token_expires_in, but Keycloak returnsrefresh_expires_in. - Extra fields, such as
not-before-policy, are present in the token response.
- Typebot expects
- The login process fails, blocking authentication entirely.
Expected behavior
It is expected that:
- Typebot accepts Keycloak’s standard token response by allowing the use of
expires_in(duration in seconds) instead of requiring an absolute epoch time forexpires_at. - The
refresh_expires_infield from Keycloak is mapped to the expectedrefresh_token_expires_infield in Typebot. - The
oauth_token_secretandoauth_tokenfields are clarified as optional or can be omitted when integrating with Keycloak. - The system gracefully handles extra or unexpected fields in the token response without blocking the login process, thereby reducing integration complexity and improving the user experience.
Code Snippets & Models
- Typebot Model (Prisma Schema)
// schema.prisma
model Account {
id String @id @default(cuid())
userId String
type String
provider String
providerAccountId String
refresh_token String? @db.Text
access_token String? @db.Text
expires_at Int?
token_type String?
scope String?
id_token String? @db.Text
session_state String?
oauth_token_secret String?
oauth_token String?
refresh_token_expires_in Int?
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([provider, providerAccountId])
@@index([userId])
}- Keycloak Token Response
public class AccessTokenResponse {
@JsonProperty("access_token")
protected String token;
@JsonProperty("expires_in")
protected long expiresIn;
@JsonProperty("refresh_expires_in")
protected long refreshExpiresIn;
@JsonProperty("refresh_token")
protected String refreshToken;
@JsonProperty("token_type")
protected String tokenType;
@JsonProperty("id_token")
protected String idToken;
@JsonProperty("not-before-policy")
protected int notBeforePolicy;
@JsonProperty("session_state")
protected String sessionState;
protected Map<String, Object> otherClaims = new HashMap();
@JsonProperty("scope")
protected String scope;
@JsonProperty("error")
protected String error;
@JsonProperty("error_description")
protected String errorDescription;
@JsonProperty("error_uri")
protected String errorUri;
}Tool Versions & Environment
For context, here are the versions used in the environment where the issue was identified:
- Typebot Builder: 3.5.0
- Keycloak Version: 26.0.6
Metadata
Metadata
Assignees
Labels
Projects
Status