Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export const GLOBAL_MENU_ITEMS: GlobalMenuItems = [
icon: 'getting-started',
href: '/guides/getting-started',
level: 'gettingstarted',
enabled: frameworkQuickstartsEnabled,
},
],
[
Expand Down
2 changes: 1 addition & 1 deletion apps/docs/content/guides/auth/sessions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ Otherwise sessions are progressively deleted from the database 24 hours after th

### What are recommended values for access token (JWT) expiration?

Most applications should use the default expiration time of 1 hour. This can be customized in your project's [Auth settings](/dashboard/project/_/auth/sessions) in the Advanced Settings section.
Most applications should use the default expiration time of 1 hour. This can be customized in your project's [Auth settings](/dashboard/project/_/settings/jwt) in the Advanced Settings section.

Setting a value over 1 hour is generally discouraged for security reasons, but it may make sense in certain situations.

Expand Down
3 changes: 3 additions & 0 deletions apps/docs/public/humans.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ Greg Kress
Greg P
Greg Richardson
Guilherme Souza
Hannah Bowers
Hardik Maheshwari
Haydn Maley
Hieu Pham
Expand Down Expand Up @@ -102,6 +103,7 @@ Matt Johnston
Matt Rossman
Monica Khoury
Mykhailo Mischa Lieibenson
Nick Littman
Nyannyacha
Oli R
Pamela Chia
Expand Down Expand Up @@ -129,6 +131,7 @@ Sreyas Udayavarman
Stanislav M
Stephen Morgan
Steve Chavez
Steven Eubank
Stojan Dimitrovski
Sugu Sougoumarane
Supun Sudaraka Kalidasa
Expand Down
227 changes: 227 additions & 0 deletions apps/docs/spec/supabase_swift_v2.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1094,6 +1094,67 @@ functions:
let session = try await supabase.auth.refreshSession(refreshToken: "custom-refresh-token")
```

- id: get-claims
title: 'getClaims()'
notes: |
- Verifies a JWT and extracts its claims.
- For symmetric JWTs (HS256), verification is performed server-side via the `getUser()` API.
- For asymmetric JWTs (RS256), verification is performed client-side using Apple Security framework.
- Uses a global JWKS cache shared across all clients with the same storage key for optimal performance.
- Automatically handles key rotation by falling back to server-side verification when a JWK is not found.
- The JWKS cache has a 10-minute TTL (time-to-live).
overwriteParams:
- name: jwt
isOptional: true
type: String
description: >
The JWT to verify. If not provided, uses the access token from the current session.
- name: options
isOptional: true
type: GetClaimsOptions
description: >
Options for JWT verification. Can specify `allowExpired` to skip expiration check and `jwks` to provide custom JSON Web Key Set.
examples:
- id: get-claims-current-session
name: Verify and get claims from current session
isSpotlight: true
code: |
```swift
let response = try await supabase.auth.getClaims()
print("User ID: \(response.claims.sub ?? "N/A")")
print("Email: \(response.claims.email ?? "N/A")")
print("Role: \(response.claims.role ?? "N/A")")
```
- id: get-claims-custom-jwt
name: Verify and get claims from a specific JWT
isSpotlight: false
code: |
```swift
let customToken = "eyJhbGci..."
let response = try await supabase.auth.getClaims(jwt: customToken)
```
- id: get-claims-allow-expired
name: Get claims from an expired JWT
description: Useful for testing or extracting information from expired tokens.
isSpotlight: false
code: |
```swift
let response = try await supabase.auth.getClaims(
options: GetClaimsOptions(allowExpired: true)
)
```
- id: get-claims-custom-jwks
name: Verify JWT with custom JWKS
description: Provide a custom JSON Web Key Set for verification.
isSpotlight: false
code: |
```swift
let customJWKS = JWKS(keys: [...])
let response = try await supabase.auth.getClaims(
options: GetClaimsOptions(jwks: customJWKS)
)
```

- id: start-auto-refresh
title: 'startAutoRefresh()'
description: |
Expand Down Expand Up @@ -1395,6 +1456,140 @@ functions:
)
```

- id: admin-oauth-list-clients
title: 'admin.oauth.listClients()'
description: |
List all OAuth clients with optional pagination.
notes: |
- Requires `service_role` key.
- This method is part of the OAuth 2.1 server administration API.
- Only works when the OAuth 2.1 server is enabled in your Supabase Auth configuration.
overwriteParams:
- name: params
isOptional: true
type: PageParams
description: >
Pagination parameters with `page` and `perPage` options.
examples:
- id: list-oauth-clients
name: List all OAuth clients
isSpotlight: true
code: |
```swift
let response = try await supabase.auth.admin.oauth.listClients()
```
- id: list-oauth-clients-paginated
name: List OAuth clients with pagination
isSpotlight: false
code: |
```swift
let response = try await supabase.auth.admin.oauth.listClients(
params: PageParams(page: 1, perPage: 10)
)
```

- id: admin-oauth-create-client
title: 'admin.oauth.createClient()'
description: |
Create a new OAuth client.
notes: |
- Requires `service_role` key.
- This method is part of the OAuth 2.1 server administration API.
- Only works when the OAuth 2.1 server is enabled in your Supabase Auth configuration.
overwriteParams:
- name: params
type: CreateOAuthClientParams
description: >
Parameters for creating the OAuth client including name, redirect URIs, and client type.
examples:
- id: create-oauth-client
name: Create a new OAuth client
isSpotlight: true
code: |
```swift
let client = try await supabase.auth.admin.oauth.createClient(
params: CreateOAuthClientParams(
name: "My OAuth App",
redirectUris: ["https://example.com/callback"],
clientType: .confidential
)
)
```

- id: admin-oauth-get-client
title: 'admin.oauth.getClient()'
description: |
Get details of a specific OAuth client.
notes: |
- Requires `service_role` key.
- This method is part of the OAuth 2.1 server administration API.
overwriteParams:
- name: clientId
type: String
description: >
The UUID of the OAuth client to retrieve.
examples:
- id: get-oauth-client
name: Get OAuth client by ID
isSpotlight: true
code: |
```swift
let client = try await supabase.auth.admin.oauth.getClient(
clientId: "12345678-1234-1234-1234-123456789012"
)
```

- id: admin-oauth-delete-client
title: 'admin.oauth.deleteClient()'
description: |
Delete an OAuth client.
notes: |
- Requires `service_role` key.
- This method is part of the OAuth 2.1 server administration API.
- This action cannot be undone.
overwriteParams:
- name: clientId
type: String
description: >
The UUID of the OAuth client to delete.
examples:
- id: delete-oauth-client
name: Delete an OAuth client
isSpotlight: true
code: |
```swift
try await supabase.auth.admin.oauth.deleteClient(
clientId: "12345678-1234-1234-1234-123456789012"
)
```

- id: admin-oauth-regenerate-client-secret
title: 'admin.oauth.regenerateClientSecret()'
description: |
Regenerate the secret for an OAuth client.
notes: |
- Requires `service_role` key.
- This method is part of the OAuth 2.1 server administration API.
- The old secret will be immediately invalidated.
- Make sure to update your application with the new secret.
overwriteParams:
- name: clientId
type: String
description: >
The UUID of the OAuth client whose secret should be regenerated.
examples:
- id: regenerate-oauth-client-secret
name: Regenerate OAuth client secret
isSpotlight: true
code: |
```swift
let client = try await supabase.auth.admin.oauth.regenerateClientSecret(
clientId: "12345678-1234-1234-1234-123456789012"
)
// The response contains the new secret
print("New secret: \(client.secret ?? "")")
```

- id: select
title: 'Fetch data: select()'
notes: |
Expand Down Expand Up @@ -4012,6 +4207,7 @@ functions:
notes: |
- Requires an Authorization header.
- When you pass in a body to your function, we automatically attach the Content-Type header for `String`, and `Data`. If it doesn't match any of these types we assume the payload is `json`, serialize it and attach the `Content-Type` header as `application/json`. You can override this behaviour by passing in a `Content-Type` header of your own.
- When a region is specified, both the `x-region` header and `forceFunctionRegion` query parameter are set to ensure proper function routing.
examples:
- id: invocation-with-decodable
name: Invocation with `Decodable` response
Expand Down Expand Up @@ -4246,6 +4442,37 @@ functions:
subscription.cancel()
```

- id: broadcast-with-replay
name: Configure broadcast with replay
description: |
Replay allows you to receive messages that were broadcast since a specific timestamp. The `meta` field in the message payload will indicate if a message is being replayed.
isSpotlight: false
code: |
```swift
let config = RealtimeJoinConfig(
broadcast: BroadcastJoinConfig(
acknowledgeBroadcasts: true,
receiveOwnBroadcasts: true,
replay: ReplayOption(
since: 1234567890,
limit: 100
)
)
)

let channel = supabase.channel("my-channel", config: config)

channel.onBroadcast { message in
if let meta = message.payload["meta"] as? [String: Any],
let replayed = meta["replayed"] as? Bool,
replayed {
print("Replayed message: \(meta["id"] ?? "")")
}
}

await channel.subscribe()
```

- id: listen-to-presence-updates
name: Listen to presence updates
code: |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useMemo } from 'react'

import { IS_PLATFORM } from 'common'
import { useOrganizationsQuery } from 'data/organizations/organizations-query'
import { useProjectsQuery } from 'data/projects/projects-query'
import { useProjectsInfiniteQuery } from 'data/projects/projects-infinite-query'
import { PageType, useRegisterCommands, useRegisterPage, useSetPage } from 'ui-patterns/CommandMenu'
import { COMMAND_MENU_SECTIONS } from './CommandMenu.utils'

Expand All @@ -13,11 +13,11 @@ const ORGANIZATION_SWITCHER_PAGE_NAME = 'Configure organization'
export function useProjectSwitchCommand() {
const setPage = useSetPage()

const { data } = useProjectsQuery({ enabled: IS_PLATFORM })
const projects = useMemo(
() => (data?.projects ?? []).map(({ name, ref }) => ({ name, ref })),
[data]
)
// [Joshen] Using paginated data here which means we won't be showing all projects
// Ideally we somehow support searching with Cmd K if we want to make this ideal
// e.g Cmd K input to support async searching while in "switch project" state
const { data } = useProjectsInfiniteQuery({}, { enabled: IS_PLATFORM })
const projects = useMemo(() => data?.pages.flatMap((page) => page.projects), [data?.pages]) || []

useRegisterPage(
PROJECT_SWITCHER_PAGE_NAME,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const OverviewLearnMore = () => {
{
label: 'Docs',
title: 'Authentication docs',
description: 'Read more on authentication and benefits of using Supabase policies.',
description: 'Read more on authentication and the benefits of using Supabase policies.',
image: `${BASE_PATH}/img/auth-overview/auth-overview-docs.jpg`,
actions: [
{
Expand Down Expand Up @@ -68,8 +68,7 @@ export const OverviewLearnMore = () => {
{
label: 'Logs',
title: 'Dive into the logs',
description:
'Our authentication logs provide a deeper view into your auth requests and errors.',
description: 'Authentication logs provide a deeper view into your auth requests.',
image: `${BASE_PATH}/img/auth-overview/auth-overview-logs.jpg`,
actions: [
{
Expand All @@ -84,7 +83,7 @@ export const OverviewLearnMore = () => {
return (
<ScaffoldSection isFullWidth>
<ScaffoldSectionTitle className="mb-4">Learn more</ScaffoldSectionTitle>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-3">
<div className="grid grid-cols-1 lg:grid-cols-3 gap-4">
{LearnMoreCards.map((card) => (
<Card key={card.label} className="relative">
<CardHeader className="absolute top-0 left-0 right-0 border-b-0">
Expand All @@ -100,12 +99,12 @@ export const OverviewLearnMore = () => {
className="object-fit"
/>
</div>
<div className="p-4">
<div className="flex flex-col gap-1 mb-4">
<div className="p-4 flex flex-col">
<div className="flex flex-col gap-1 mb-4 flex-1">
<h4>{card.title}</h4>
<p className="text-sm text-foreground-lighter">{card.description}</p>
</div>
<div className="flex flex-col gap-2 items-start">
<div className="flex flex-col gap-2 items-start mt-auto">
{card.actions.map((action) => {
if ('href' in action) {
return (
Expand Down
Loading
Loading