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
5 changes: 5 additions & 0 deletions .changeset/quiet-dolphins-swim.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@clerk/ui': minor
---

Handle `offline_access` scope in OAuth consent screen by filtering it from the displayed scopes list (as it describes access duration rather than what can be accessed) and appending informational text about staying signed in when the scope is present.
3 changes: 2 additions & 1 deletion packages/clerk-js/sandbox/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,8 @@ void (async () => {
const searchParams = new URLSearchParams(window.location.search);
const scopes = (searchParams.get('scopes')?.split(',') ?? []).map(scope => ({
scope,
description: `Grants access to your ${scope}`,
description: scope === 'offline_access' ? null : `Grants access to your ${scope}`,
requires_consent: true,
}));
Clerk.__internal_mountOAuthConsent(
app,
Expand Down
4 changes: 2 additions & 2 deletions packages/ui/bundlewatch.config.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"files": [
{ "path": "./dist/ui.browser.js", "maxSize": "34KB" },
{ "path": "./dist/ui.legacy.browser.js", "maxSize": "72KB" },
{ "path": "./dist/ui.browser.js", "maxSize": "36KB" },
{ "path": "./dist/ui.legacy.browser.js", "maxSize": "74KB" },
{ "path": "./dist/framework*.js", "maxSize": "44KB" },
{ "path": "./dist/vendors*.js", "maxSize": "73KB" },
{ "path": "./dist/ui-common*.js", "maxSize": "130KB" },
Expand Down
9 changes: 8 additions & 1 deletion packages/ui/src/components/OAuthConsent/OAuthConsent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import type { ThemableCssProp } from '@/ui/styledSystem';
import { common } from '@/ui/styledSystem';
import { colors } from '@/ui/utils/colors';

const OFFLINE_ACCESS_SCOPE = 'offline_access';

export function OAuthConsentInternal() {
const { scopes, oAuthApplicationName, oAuthApplicationLogoUrl, oAuthApplicationUrl, redirectUrl, onDeny, onAllow } =
useOAuthConsentContext();
Expand All @@ -25,6 +27,10 @@ export function OAuthConsentInternal() {

const primaryEmailAddress = user?.emailAddresses.find(email => email.id === user.primaryEmailAddress?.id);

// Filter out offline_access from displayed scopes as it doesn't describe what can be accessed
const displayedScopes = (scopes || []).filter(item => item.scope !== OFFLINE_ACCESS_SCOPE);
const hasOfflineAccess = (scopes || []).some(item => item.scope === OFFLINE_ACCESS_SCOPE);

function getRootDomain(): string {
try {
const { hostname } = new URL(redirectUrl);
Expand Down Expand Up @@ -132,7 +138,7 @@ export function OAuthConsentInternal() {
as='ul'
sx={t => ({ margin: t.sizes.$none, padding: t.sizes.$none })}
>
{(scopes || []).map(item => (
{displayedScopes.map(item => (
<Box
key={item.scope}
sx={t => ({
Expand Down Expand Up @@ -240,6 +246,7 @@ export function OAuthConsentInternal() {
</Tooltip.Trigger>
<Tooltip.Content text={`View full URL`} />
</Tooltip.Root>
.{hasOfflineAccess && " You'll stay signed in until you sign out or revoke access."}
</Text>
</Grid>
</Card.Content>
Expand Down
Loading