d718c5a372
CI / compile_and_lint (push) Failing after 0s
CI / docker_build (linux/amd64, -linux-amd64-duckdb, duckdb) (push) Failing after 0s
CI / docker_build (linux/arm64, -linux-arm64, minimal) (push) Failing after 2s
CI / docker_build (linux/arm64, -linux-arm64-duckdb, duckdb) (push) Failing after 1s
CI / docker_build (linux/amd64, minimal) (push) Failing after 1s
CI / test (, sqlite, sqlite::memory:) (push) Has been skipped
CI / test (mssql, mssql, mssql://root:Password123!@127.0.0.1/sqlpage) (push) Has been skipped
CI / test (mysql, mysql, mysql://root:Password123!@127.0.0.1/sqlpage) (push) Has been skipped
CI / test (oracle, oracle, Driver=Oracle 21 ODBC driver;Dbq=//127.0.0.1:1521/FREEPDB1;Uid=root;Pwd=Password123!) (push) Has been skipped
CI / test (postgres, odbc, Driver=PostgreSQL Unicode;Server=127.0.0.1;Port=5432;Database=sqlpage;UID=root;PWD=Password123!, true) (push) Has been skipped
CI / test (postgres, postgres, postgres://root:Password123!@127.0.0.1/sqlpage) (push) Has been skipped
CI / playwright (push) Has been skipped
CI / docker_build (linux/arm/v7, -linux-arm-v7, minimal) (push) Failing after 0s
CI / hurl_examples (push) Failing after 8s
deploy website / deploy_official_site (push) Failing after 1s
CI / hurl (${{ matrix.example }}) (push) Has been skipped
CI / docker_push (duckdb) (push) Has been cancelled
CI / docker_push (minimal) (push) Has been cancelled
CI / windows_test (push) Has been cancelled
294 lines
9.5 KiB
SQL
294 lines
9.5 KiB
SQL
INSERT INTO
|
|
sqlpage_functions (
|
|
"name",
|
|
"introduced_in_version",
|
|
"icon",
|
|
"description_md"
|
|
)
|
|
VALUES
|
|
(
|
|
'user_info_token',
|
|
'0.35.0',
|
|
'key',
|
|
'# Accessing information about the current user, when logged in with SSO
|
|
|
|
This function can be used only when you have [configured Single Sign-On with an OIDC provider](/sso).
|
|
|
|
## The ID Token
|
|
|
|
When a user logs in through OIDC, your application receives an [identity token](https://openid.net/specs/openid-connect-core-1_0.html#IDToken) from the identity provider.
|
|
This token contains information about the user, such as their name and email address.
|
|
The `sqlpage.user_info_token()` function lets you access the entire contents of the ID token, as a JSON object.
|
|
You can then use [your database''s JSON functions](/blog.sql?post=JSON+in+SQL%3A+A+Comprehensive+Guide) to process that JSON.
|
|
|
|
If you need to access a specific claim, it is easier and more performant to use the
|
|
[`sqlpage.user_info()`](?function=user_info) function instead.
|
|
|
|
### Example: Displaying User Information
|
|
|
|
```sql
|
|
select ''list'' as component;
|
|
select key as title, value as description
|
|
from json_each(sqlpage.user_info_token());
|
|
```
|
|
|
|
This sqlite-specific example will show all the information available about the current user, such as:
|
|
- `sub`: A unique identifier for the user
|
|
- `name`: The user''s full name
|
|
- `email`: The user''s email address
|
|
- `picture`: A URL to the user''s profile picture
|
|
|
|
### Security Notes
|
|
|
|
- The ID token is automatically verified by SQLPage to ensure it hasn''t been tampered with.
|
|
- The token is only available to authenticated users: if no user is logged in or sso is not configured, this function returns NULL
|
|
- If some information is not available in the token, you have to configure it on your OIDC provider, SQLPage can''t do anything about it.
|
|
- The token is stored in a signed http-only cookie named `sqlpage_auth`. You can use [the cookie component](/component.sql?component=cookie) to delete it, and the user will be redirected to the login page on the next page load.
|
|
'
|
|
);
|
|
|
|
INSERT INTO
|
|
sqlpage_functions (
|
|
"name",
|
|
"introduced_in_version",
|
|
"icon",
|
|
"description_md"
|
|
)
|
|
VALUES
|
|
(
|
|
'user_info',
|
|
'0.34.0',
|
|
'user',
|
|
'# Accessing Specific User Information
|
|
|
|
The `sqlpage.user_info` function is a convenient way to access specific pieces of information about the currently logged-in user.
|
|
When you [configure Single Sign-On](/sso), your OIDC provider will issue an [ID token](https://openid.net/specs/openid-connect-core-1_0.html#IDToken) for the user,
|
|
which contains *claims*, with information about the user.
|
|
|
|
Calling `sqlpage.user_info(claim_name)` lets you access these claims directly from SQL.
|
|
|
|
## How to Use
|
|
|
|
The function takes one parameter: the name of the *claim* (the piece of information you want to retrieve).
|
|
|
|
For example, to display a personalized welcome message, with the user''s name, you can use:
|
|
|
|
```sql
|
|
select ''text'' as component;
|
|
select ''Welcome, '' || sqlpage.user_info(''name'') || ''!'' as title;
|
|
```
|
|
|
|
## Available Information
|
|
|
|
The exact information available depends on your identity provider (the service you chose to authenticate with),
|
|
its configuration, and the scopes you requested.
|
|
Use [`sqlpage.user_info_token()`](?function=user_info_token) to see all the information available in the ID token of the current user.
|
|
|
|
Here are some commonly available fields:
|
|
|
|
### Basic Information
|
|
- `name`: The user''s full name (usually first and last name separated by a space)
|
|
- `email`: The user''s email address (*warning*: there is no guarantee that the user currently controls this email address. Use the `sub` claim for database references instead.)
|
|
- `picture`: URL to the user''s profile picture
|
|
|
|
### User Identifiers
|
|
- `sub`: A unique identifier for the user (use this to uniquely identify the user in your database)
|
|
- `preferred_username`: The username the user prefers to use
|
|
|
|
### Name Components
|
|
- `given_name`: The user''s first name
|
|
- `family_name`: The user''s last name
|
|
|
|
## Examples
|
|
|
|
### Personalized Welcome Message
|
|
```sql
|
|
select ''text'' as component,
|
|
''Welcome back, **'' || sqlpage.user_info(''given_name'') || ''**!'' as contents_md;
|
|
```
|
|
|
|
### User Profile Card
|
|
```sql
|
|
select ''card'' as component;
|
|
select
|
|
sqlpage.user_info(''name'') as title,
|
|
sqlpage.user_info(''email'') as description,
|
|
sqlpage.user_info(''picture'') as image;
|
|
```
|
|
|
|
### Conditional Content Based on custom claims
|
|
|
|
Some identity providers let you add custom claims to the ID token.
|
|
This lets you customize the behavior of your application based on arbitrary user attributes,
|
|
such as the user''s role.
|
|
|
|
```sql
|
|
-- show everything to admins, only public items to others
|
|
select ''list'' as component;
|
|
select title from my_items
|
|
where is_public or sqlpage.user_info(''role'') = ''admin''
|
|
```
|
|
|
|
## Security Best Practices
|
|
|
|
> ⚠️ **Important**: Always use the `sub` claim to identify users in your database, not their email address.
|
|
> The `sub` claim is guaranteed to be unique and stable for each user, while email addresses can change.
|
|
> In most providers, receiving an id token with a given email does not guarantee that the user currently controls that email.
|
|
|
|
```sql
|
|
-- Store the user''s ID in your database
|
|
insert into user_preferences (user_id, theme)
|
|
values (sqlpage.user_info(''sub''), ''dark'');
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
If you''re not getting the information you expect:
|
|
|
|
1. Check that OIDC is properly configured in your `sqlpage.json`
|
|
2. Verify that you requested the right scopes in your OIDC configuration
|
|
3. Try using `sqlpage.user_info_token()` to see all available information
|
|
4. Check your OIDC provider''s documentation for the exact claim names they use
|
|
|
|
Remember: If the user is not logged in or the requested information is not available, this function returns NULL.
|
|
'
|
|
);
|
|
|
|
INSERT INTO
|
|
sqlpage_function_parameters (
|
|
"function",
|
|
"index",
|
|
"name",
|
|
"description_md",
|
|
"type"
|
|
)
|
|
VALUES
|
|
(
|
|
'user_info',
|
|
1,
|
|
'claim',
|
|
'The name of the user information to retrieve. Common values include ''name'', ''email'', ''picture'', ''sub'', ''preferred_username'', ''given_name'', and ''family_name''. The exact values available depend on your OIDC provider and configuration.',
|
|
'TEXT'
|
|
);
|
|
|
|
INSERT INTO
|
|
sqlpage_functions (
|
|
"name",
|
|
"introduced_in_version",
|
|
"icon",
|
|
"description_md"
|
|
)
|
|
VALUES
|
|
(
|
|
'oidc_logout_url',
|
|
'0.41.0',
|
|
'logout',
|
|
'# Secure OIDC Logout
|
|
|
|
The `sqlpage.oidc_logout_url` function generates a secure logout URL for users authenticated via [OIDC Single Sign-On](/sso).
|
|
|
|
When a user visits this URL, SQLPage will:
|
|
1. Remove the authentication cookie
|
|
2. Redirect the user to the OIDC provider''s logout endpoint (if available)
|
|
3. Finally redirect back to the specified `redirect_uri`
|
|
|
|
## Security Features
|
|
|
|
This function provides protection against **Cross-Site Request Forgery (CSRF)** attacks:
|
|
- The generated URL contains a cryptographically signed token
|
|
- The token includes a timestamp and expires after 10 minutes
|
|
- The token is signed using your OIDC client secret
|
|
- Only relative URLs (starting with `/`) are allowed as redirect targets
|
|
|
|
This means that malicious websites cannot trick your users into logging out by simply including an image or link to your logout URL.
|
|
|
|
## How to Use
|
|
|
|
```sql
|
|
select ''button'' as component;
|
|
select
|
|
''Logout'' as title,
|
|
sqlpage.oidc_logout_url(''/'') as link,
|
|
''logout'' as icon,
|
|
''red'' as outline;
|
|
```
|
|
|
|
This creates a logout button that, when clicked:
|
|
1. Logs the user out of your SQLPage application
|
|
2. Logs the user out of the OIDC provider (if the provider supports [RP-Initiated Logout](https://openid.net/specs/openid-connect-rpinitiated-1_0.html))
|
|
3. Redirects the user back to your homepage (`/`)
|
|
|
|
## Examples
|
|
|
|
### Logout Button in Navigation
|
|
|
|
```sql
|
|
select ''shell'' as component,
|
|
''My App'' as title,
|
|
json_array(
|
|
json_object(
|
|
''title'', ''Logout'',
|
|
''link'', sqlpage.oidc_logout_url(''/''),
|
|
''icon'', ''logout''
|
|
)
|
|
) as menu_item;
|
|
```
|
|
|
|
### Logout with Return to Current Page
|
|
|
|
```sql
|
|
select ''button'' as component;
|
|
select
|
|
''Sign Out'' as title,
|
|
sqlpage.oidc_logout_url(sqlpage.path()) as link;
|
|
```
|
|
|
|
### Conditional Logout Link
|
|
|
|
```sql
|
|
select ''button'' as component
|
|
where sqlpage.user_info(''sub'') is not null;
|
|
select
|
|
''Logout '' || sqlpage.user_info(''name'') as title,
|
|
sqlpage.oidc_logout_url(''/'') as link
|
|
where sqlpage.user_info(''sub'') is not null;
|
|
```
|
|
|
|
## Requirements
|
|
|
|
- OIDC must be [configured](/sso) in your `sqlpage.json`
|
|
- If OIDC is not configured, this function returns NULL
|
|
- The `redirect_uri` must be a relative path starting with `/`
|
|
|
|
## Provider Support
|
|
|
|
The logout behavior depends on your OIDC provider:
|
|
|
|
| Provider | Full Logout Support |
|
|
|----------|-------------------|
|
|
| Keycloak | ✅ Yes |
|
|
| Auth0 | ✅ Yes |
|
|
| Google | ❌ No (local logout only) |
|
|
| Azure AD | ✅ Yes |
|
|
| Okta | ✅ Yes |
|
|
|
|
When the provider doesn''t support RP-Initiated Logout, SQLPage will still remove the local authentication cookie and redirect to your specified URI.
|
|
'
|
|
);
|
|
|
|
INSERT INTO
|
|
sqlpage_function_parameters (
|
|
"function",
|
|
"index",
|
|
"name",
|
|
"description_md",
|
|
"type"
|
|
)
|
|
VALUES
|
|
(
|
|
'oidc_logout_url',
|
|
1,
|
|
'redirect_uri',
|
|
'The relative URL path where the user should be redirected after logout. Must start with `/`. Defaults to `/` if not provided.',
|
|
'TEXT'
|
|
); |