0c9a9ea24d
This PR fixes multiple OAuth-related issues: ## Unified OAuth Callback - Consolidated `/oauth/callback-nextcloud` and `/oauth/login-callback` into single `/oauth/callback` endpoint - Flow type determined by session lookup via state parameter (no query params in redirect_uri) - Fixes redirect_uri validation issues with IdPs requiring exact match - Legacy endpoints kept as aliases for backwards compatibility ## PKCE Implementation - Implemented PKCE (RFC 7636) for Flow 2 (resource provisioning) - Generate code_verifier and code_challenge - Store code_verifier in session storage - Retrieve and use in token exchange - Fixed PKCE for browser login (integrated mode) - Previously only worked for external IdP (Keycloak) - Now works for both Nextcloud OIDC and external IdP ## Login Elicitation Fixes (ADR-006) - Fixed elicitation URL to route through MCP server endpoint - Changed from direct Nextcloud URL to `/oauth/authorize-nextcloud` - Ensures PKCE is properly handled by server - Fixed login detection after OAuth flow completes - Look up refresh token by state parameter instead of user_id - Works even when Flow 1 token not present - Added `get_refresh_token_by_provisioning_client_id()` method ## Session Authentication - Fixed `/user/page` redirect loop - Shared oauth_context with mounted browser_app - SessionAuthBackend can now validate sessions correctly ## Tests - Added comprehensive login elicitation test suite - Updated scope authorization test expectations - All 43 OAuth tests passing ## Files Changed - `app.py`: Shared oauth_context, unified callback route - `oauth_routes.py`: Unified callback, PKCE for Flow 2 - `browser_oauth_routes.py`: PKCE for integrated mode - `oauth_tools.py`: Fixed elicitation URL generation - `refresh_token_storage.py`: Added lookup by provisioning_client_id - `test_login_elicitation.py`: New test suite 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
853 lines
24 KiB
JSON
853 lines
24 KiB
JSON
{
|
|
"id": "nextcloud-mcp",
|
|
"realm": "nextcloud-mcp",
|
|
"notBefore": 0,
|
|
"defaultSignatureAlgorithm": "RS256",
|
|
"revokeRefreshToken": false,
|
|
"refreshTokenMaxReuse": 0,
|
|
"accessTokenLifespan": 300,
|
|
"accessTokenLifespanForImplicitFlow": 900,
|
|
"ssoSessionIdleTimeout": 1800,
|
|
"ssoSessionMaxLifespan": 36000,
|
|
"offlineSessionIdleTimeout": 2592000,
|
|
"offlineSessionMaxLifespanEnabled": false,
|
|
"offlineSessionMaxLifespan": 5184000,
|
|
"accessCodeLifespan": 60,
|
|
"accessCodeLifespanUserAction": 300,
|
|
"accessCodeLifespanLogin": 1800,
|
|
"enabled": true,
|
|
"sslRequired": "external",
|
|
"registrationAllowed": false,
|
|
"loginWithEmailAllowed": true,
|
|
"duplicateEmailsAllowed": false,
|
|
"resetPasswordAllowed": false,
|
|
"editUsernameAllowed": false,
|
|
"bruteForceProtected": false,
|
|
"attributes": {
|
|
"frontendUrl": "http://localhost:8888"
|
|
},
|
|
"roles": {
|
|
"realm": [
|
|
{
|
|
"name": "offline_access",
|
|
"description": "${role_offline-access}",
|
|
"composite": false,
|
|
"clientRole": false
|
|
},
|
|
{
|
|
"name": "uma_authorization",
|
|
"description": "${role_uma_authorization}",
|
|
"composite": false,
|
|
"clientRole": false
|
|
},
|
|
{
|
|
"name": "default-roles-nextcloud-mcp",
|
|
"description": "${role_default-roles}",
|
|
"composite": true,
|
|
"composites": {
|
|
"realm": [
|
|
"offline_access",
|
|
"uma_authorization"
|
|
]
|
|
},
|
|
"clientRole": false
|
|
}
|
|
]
|
|
},
|
|
"users": [
|
|
{
|
|
"username": "admin",
|
|
"enabled": true,
|
|
"email": "admin@example.com",
|
|
"emailVerified": true,
|
|
"firstName": "Admin",
|
|
"lastName": "User",
|
|
"credentials": [
|
|
{
|
|
"type": "password",
|
|
"value": "admin",
|
|
"temporary": false
|
|
}
|
|
],
|
|
"realmRoles": [
|
|
"default-roles-nextcloud-mcp",
|
|
"offline_access"
|
|
],
|
|
"attributes": {
|
|
"quota": [
|
|
"1073741824"
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"username": "test_read_only",
|
|
"enabled": true,
|
|
"email": "readonly@example.com",
|
|
"emailVerified": true,
|
|
"firstName": "Read",
|
|
"lastName": "Only",
|
|
"credentials": [
|
|
{
|
|
"type": "password",
|
|
"value": "test123",
|
|
"temporary": false
|
|
}
|
|
],
|
|
"realmRoles": [
|
|
"default-roles-nextcloud-mcp",
|
|
"offline_access"
|
|
],
|
|
"attributes": {
|
|
"quota": [
|
|
"1073741824"
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"username": "test_write_only",
|
|
"enabled": true,
|
|
"email": "writeonly@example.com",
|
|
"emailVerified": true,
|
|
"firstName": "Write",
|
|
"lastName": "Only",
|
|
"credentials": [
|
|
{
|
|
"type": "password",
|
|
"value": "test123",
|
|
"temporary": false
|
|
}
|
|
],
|
|
"realmRoles": [
|
|
"default-roles-nextcloud-mcp",
|
|
"offline_access"
|
|
],
|
|
"attributes": {
|
|
"quota": [
|
|
"1073741824"
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"username": "test_no_scopes",
|
|
"enabled": true,
|
|
"email": "noscopes@example.com",
|
|
"emailVerified": true,
|
|
"firstName": "No",
|
|
"lastName": "Scopes",
|
|
"credentials": [
|
|
{
|
|
"type": "password",
|
|
"value": "test123",
|
|
"temporary": false
|
|
}
|
|
],
|
|
"realmRoles": [
|
|
"default-roles-nextcloud-mcp",
|
|
"offline_access"
|
|
],
|
|
"attributes": {
|
|
"quota": [
|
|
"1073741824"
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"username": "service-account-nextcloud-mcp-server",
|
|
"enabled": true,
|
|
"serviceAccountClientId": "nextcloud-mcp-server",
|
|
"clientRoles": {
|
|
"realm-management": [
|
|
"impersonation"
|
|
]
|
|
}
|
|
}
|
|
],
|
|
"clients": [
|
|
{
|
|
"clientId": "nextcloud",
|
|
"name": "Nextcloud Resource Server",
|
|
"description": "Resource server for Nextcloud APIs - used by user_oidc app for bearer token validation and as token exchange target",
|
|
"enabled": true,
|
|
"clientAuthenticatorType": "client-secret",
|
|
"secret": "nextcloud-secret-change-in-production",
|
|
"redirectUris": [],
|
|
"webOrigins": [],
|
|
"bearerOnly": false,
|
|
"consentRequired": false,
|
|
"standardFlowEnabled": false,
|
|
"implicitFlowEnabled": false,
|
|
"directAccessGrantsEnabled": false,
|
|
"serviceAccountsEnabled": true,
|
|
"authorizationServicesEnabled": true,
|
|
"publicClient": false,
|
|
"protocol": "openid-connect",
|
|
"attributes": {
|
|
"display.on.consent.screen": "false",
|
|
"token.exchange.grant.enabled": "true",
|
|
"client.token.exchange.standard.enabled": "true",
|
|
"standard.token.exchange.enabled": "true"
|
|
},
|
|
"authorizationSettings": {
|
|
"allowRemoteResourceManagement": true,
|
|
"policyEnforcementMode": "ENFORCING",
|
|
"resources": [
|
|
{
|
|
"name": "token-exchange",
|
|
"type": "urn:keycloak:token-exchange",
|
|
"ownerManagedAccess": false,
|
|
"displayName": "Token Exchange",
|
|
"attributes": {},
|
|
"uris": [],
|
|
"scopes": [
|
|
{
|
|
"name": "token-exchange"
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"policies": [
|
|
{
|
|
"name": "allow-nextcloud-mcp-server-to-exchange",
|
|
"description": "",
|
|
"type": "client",
|
|
"logic": "POSITIVE",
|
|
"decisionStrategy": "UNANIMOUS",
|
|
"config": {
|
|
"clients": "[\"nextcloud-mcp-server\",\"nextcloud\"]"
|
|
}
|
|
},
|
|
{
|
|
"name": "token-exchange-permission",
|
|
"description": "",
|
|
"type": "scope",
|
|
"logic": "POSITIVE",
|
|
"decisionStrategy": "AFFIRMATIVE",
|
|
"config": {
|
|
"resources": "[\"token-exchange\"]",
|
|
"scopes": "[\"token-exchange\"]",
|
|
"applyPolicies": "[\"allow-nextcloud-mcp-server-to-exchange\"]"
|
|
}
|
|
}
|
|
],
|
|
"scopes": [
|
|
{
|
|
"name": "token-exchange",
|
|
"displayName": "Token Exchange"
|
|
}
|
|
],
|
|
"decisionStrategy": "UNANIMOUS"
|
|
},
|
|
"fullScopeAllowed": true,
|
|
"nodeReRegistrationTimeout": -1
|
|
},
|
|
{
|
|
"clientId": "nextcloud-mcp-server",
|
|
"name": "Nextcloud MCP Server",
|
|
"enabled": true,
|
|
"clientAuthenticatorType": "client-secret",
|
|
"secret": "mcp-secret-change-in-production",
|
|
"redirectUris": [
|
|
"http://localhost:*",
|
|
"http://127.0.0.1:*",
|
|
"http://localhost:*/callback",
|
|
"http://127.0.0.1:*/callback"
|
|
],
|
|
"webOrigins": [
|
|
"+"
|
|
],
|
|
"bearerOnly": false,
|
|
"consentRequired": false,
|
|
"standardFlowEnabled": true,
|
|
"implicitFlowEnabled": false,
|
|
"directAccessGrantsEnabled": true,
|
|
"serviceAccountsEnabled": true,
|
|
"publicClient": false,
|
|
"frontchannelLogout": false,
|
|
"protocol": "openid-connect",
|
|
"attributes": {
|
|
"pkce.code.challenge.method": "S256",
|
|
"use.refresh.tokens": "true",
|
|
"backchannel.logout.session.required": "true",
|
|
"backchannel.logout.url": "http://app:80/index.php/apps/user_oidc/backchannel-logout/keycloak",
|
|
"oauth2.device.authorization.grant.enabled": "false",
|
|
"oidc.ciba.grant.enabled": "false",
|
|
"client_credentials.use_refresh_token": "false",
|
|
"display.on.consent.screen": "false",
|
|
"token.exchange.grant.enabled": "true",
|
|
"client.token.exchange.standard.enabled": "true",
|
|
"standard.token.exchange.enabled": "true"
|
|
},
|
|
"fullScopeAllowed": true,
|
|
"nodeReRegistrationTimeout": -1,
|
|
"protocolMappers": [
|
|
{
|
|
"name": "mcp-server-audience",
|
|
"protocol": "openid-connect",
|
|
"protocolMapper": "oidc-audience-mapper",
|
|
"consentRequired": false,
|
|
"config": {
|
|
"included.client.audience": "nextcloud-mcp-server",
|
|
"access.token.claim": "true",
|
|
"id.token.claim": "false",
|
|
"introspection.token.claim": "true"
|
|
}
|
|
},
|
|
{
|
|
"name": "nextcloud-audience",
|
|
"protocol": "openid-connect",
|
|
"protocolMapper": "oidc-audience-mapper",
|
|
"consentRequired": false,
|
|
"config": {
|
|
"included.client.audience": "nextcloud",
|
|
"access.token.claim": "true",
|
|
"id.token.claim": "false",
|
|
"introspection.token.claim": "true"
|
|
}
|
|
},
|
|
{
|
|
"name": "sub",
|
|
"protocol": "openid-connect",
|
|
"protocolMapper": "oidc-usermodel-property-mapper",
|
|
"consentRequired": false,
|
|
"config": {
|
|
"userinfo.token.claim": "true",
|
|
"user.attribute": "username",
|
|
"id.token.claim": "true",
|
|
"access.token.claim": "true",
|
|
"claim.name": "sub",
|
|
"jsonType.label": "String"
|
|
}
|
|
},
|
|
{
|
|
"name": "full name",
|
|
"protocol": "openid-connect",
|
|
"protocolMapper": "oidc-full-name-mapper",
|
|
"consentRequired": false,
|
|
"config": {
|
|
"id.token.claim": "true",
|
|
"access.token.claim": "true",
|
|
"userinfo.token.claim": "true"
|
|
}
|
|
},
|
|
{
|
|
"name": "email",
|
|
"protocol": "openid-connect",
|
|
"protocolMapper": "oidc-usermodel-property-mapper",
|
|
"consentRequired": false,
|
|
"config": {
|
|
"userinfo.token.claim": "true",
|
|
"user.attribute": "email",
|
|
"id.token.claim": "true",
|
|
"access.token.claim": "true",
|
|
"claim.name": "email",
|
|
"jsonType.label": "String"
|
|
}
|
|
},
|
|
{
|
|
"name": "preferred_username",
|
|
"protocol": "openid-connect",
|
|
"protocolMapper": "oidc-usermodel-property-mapper",
|
|
"consentRequired": false,
|
|
"config": {
|
|
"userinfo.token.claim": "true",
|
|
"user.attribute": "username",
|
|
"id.token.claim": "true",
|
|
"access.token.claim": "true",
|
|
"claim.name": "preferred_username",
|
|
"jsonType.label": "String"
|
|
}
|
|
},
|
|
{
|
|
"name": "quota",
|
|
"protocol": "openid-connect",
|
|
"protocolMapper": "oidc-usermodel-attribute-mapper",
|
|
"consentRequired": false,
|
|
"config": {
|
|
"userinfo.token.claim": "true",
|
|
"user.attribute": "quota",
|
|
"id.token.claim": "true",
|
|
"access.token.claim": "true",
|
|
"claim.name": "quota",
|
|
"jsonType.label": "String"
|
|
}
|
|
}
|
|
],
|
|
"defaultClientScopes": [
|
|
"web-origins",
|
|
"profile",
|
|
"roles",
|
|
"email"
|
|
],
|
|
"optionalClientScopes": [
|
|
"address",
|
|
"phone",
|
|
"offline_access",
|
|
"microprofile-jwt",
|
|
"notes:read",
|
|
"notes:write",
|
|
"calendar:read",
|
|
"calendar:write",
|
|
"contacts:read",
|
|
"contacts:write",
|
|
"cookbook:read",
|
|
"cookbook:write",
|
|
"deck:read",
|
|
"deck:write",
|
|
"tables:read",
|
|
"tables:write",
|
|
"files:read",
|
|
"files:write",
|
|
"sharing:read",
|
|
"sharing:write",
|
|
"todo:read",
|
|
"todo:write"
|
|
]
|
|
}
|
|
],
|
|
"clientScopes": [
|
|
{
|
|
"name": "offline_access",
|
|
"description": "OpenID Connect built-in scope: offline_access",
|
|
"protocol": "openid-connect",
|
|
"attributes": {
|
|
"consent.screen.text": "${offlineAccessScopeConsentText}",
|
|
"display.on.consent.screen": "true"
|
|
}
|
|
},
|
|
{
|
|
"name": "profile",
|
|
"description": "OpenID Connect built-in scope: profile",
|
|
"protocol": "openid-connect",
|
|
"attributes": {
|
|
"include.in.token.scope": "true",
|
|
"display.on.consent.screen": "true"
|
|
},
|
|
"protocolMappers": [
|
|
{
|
|
"name": "full name",
|
|
"protocol": "openid-connect",
|
|
"protocolMapper": "oidc-full-name-mapper",
|
|
"consentRequired": false,
|
|
"config": {
|
|
"id.token.claim": "true",
|
|
"access.token.claim": "true",
|
|
"userinfo.token.claim": "true"
|
|
}
|
|
},
|
|
{
|
|
"name": "username",
|
|
"protocol": "openid-connect",
|
|
"protocolMapper": "oidc-usermodel-property-mapper",
|
|
"consentRequired": false,
|
|
"config": {
|
|
"userinfo.token.claim": "true",
|
|
"user.attribute": "username",
|
|
"id.token.claim": "true",
|
|
"access.token.claim": "true",
|
|
"claim.name": "preferred_username",
|
|
"jsonType.label": "String"
|
|
}
|
|
},
|
|
{
|
|
"name": "given name",
|
|
"protocol": "openid-connect",
|
|
"protocolMapper": "oidc-usermodel-property-mapper",
|
|
"consentRequired": false,
|
|
"config": {
|
|
"userinfo.token.claim": "true",
|
|
"user.attribute": "firstName",
|
|
"id.token.claim": "true",
|
|
"access.token.claim": "true",
|
|
"claim.name": "given_name",
|
|
"jsonType.label": "String"
|
|
}
|
|
},
|
|
{
|
|
"name": "family name",
|
|
"protocol": "openid-connect",
|
|
"protocolMapper": "oidc-usermodel-property-mapper",
|
|
"consentRequired": false,
|
|
"config": {
|
|
"userinfo.token.claim": "true",
|
|
"user.attribute": "lastName",
|
|
"id.token.claim": "true",
|
|
"access.token.claim": "true",
|
|
"claim.name": "family_name",
|
|
"jsonType.label": "String"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"name": "email",
|
|
"description": "OpenID Connect built-in scope: email",
|
|
"protocol": "openid-connect",
|
|
"attributes": {
|
|
"include.in.token.scope": "true",
|
|
"display.on.consent.screen": "true"
|
|
},
|
|
"protocolMappers": [
|
|
{
|
|
"name": "email",
|
|
"protocol": "openid-connect",
|
|
"protocolMapper": "oidc-usermodel-property-mapper",
|
|
"consentRequired": false,
|
|
"config": {
|
|
"userinfo.token.claim": "true",
|
|
"user.attribute": "email",
|
|
"id.token.claim": "true",
|
|
"access.token.claim": "true",
|
|
"claim.name": "email",
|
|
"jsonType.label": "String"
|
|
}
|
|
},
|
|
{
|
|
"name": "email verified",
|
|
"protocol": "openid-connect",
|
|
"protocolMapper": "oidc-usermodel-property-mapper",
|
|
"consentRequired": false,
|
|
"config": {
|
|
"userinfo.token.claim": "true",
|
|
"user.attribute": "emailVerified",
|
|
"id.token.claim": "true",
|
|
"access.token.claim": "true",
|
|
"claim.name": "email_verified",
|
|
"jsonType.label": "boolean"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"name": "roles",
|
|
"description": "OpenID Connect scope for add user roles to the access token",
|
|
"protocol": "openid-connect",
|
|
"attributes": {
|
|
"include.in.token.scope": "false",
|
|
"display.on.consent.screen": "true"
|
|
},
|
|
"protocolMappers": [
|
|
{
|
|
"name": "realm roles",
|
|
"protocol": "openid-connect",
|
|
"protocolMapper": "oidc-usermodel-realm-role-mapper",
|
|
"consentRequired": false,
|
|
"config": {
|
|
"user.attribute": "foo",
|
|
"access.token.claim": "true",
|
|
"claim.name": "realm_access.roles",
|
|
"jsonType.label": "String",
|
|
"multivalued": "true"
|
|
}
|
|
},
|
|
{
|
|
"name": "client roles",
|
|
"protocol": "openid-connect",
|
|
"protocolMapper": "oidc-usermodel-client-role-mapper",
|
|
"consentRequired": false,
|
|
"config": {
|
|
"user.attribute": "foo",
|
|
"access.token.claim": "true",
|
|
"claim.name": "resource_access.${client_id}.roles",
|
|
"jsonType.label": "String",
|
|
"multivalued": "true"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"name": "web-origins",
|
|
"description": "OpenID Connect scope for add allowed web origins to the access token",
|
|
"protocol": "openid-connect",
|
|
"attributes": {
|
|
"include.in.token.scope": "false",
|
|
"display.on.consent.screen": "false"
|
|
},
|
|
"protocolMappers": [
|
|
{
|
|
"name": "allowed web origins",
|
|
"protocol": "openid-connect",
|
|
"protocolMapper": "oidc-allowed-origins-mapper",
|
|
"consentRequired": false,
|
|
"config": {}
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"name": "notes:read",
|
|
"description": "Nextcloud Notes read access",
|
|
"protocol": "openid-connect",
|
|
"attributes": {
|
|
"include.in.token.scope": "true",
|
|
"display.on.consent.screen": "true",
|
|
"consent.screen.text": "Read your notes"
|
|
}
|
|
},
|
|
{
|
|
"name": "notes:write",
|
|
"description": "Nextcloud Notes write access",
|
|
"protocol": "openid-connect",
|
|
"attributes": {
|
|
"include.in.token.scope": "true",
|
|
"display.on.consent.screen": "true",
|
|
"consent.screen.text": "Create, update, and delete your notes"
|
|
}
|
|
},
|
|
{
|
|
"name": "calendar:read",
|
|
"description": "Nextcloud Calendar read access",
|
|
"protocol": "openid-connect",
|
|
"attributes": {
|
|
"include.in.token.scope": "true",
|
|
"display.on.consent.screen": "true",
|
|
"consent.screen.text": "Read your calendars and events"
|
|
}
|
|
},
|
|
{
|
|
"name": "calendar:write",
|
|
"description": "Nextcloud Calendar write access",
|
|
"protocol": "openid-connect",
|
|
"attributes": {
|
|
"include.in.token.scope": "true",
|
|
"display.on.consent.screen": "true",
|
|
"consent.screen.text": "Create, update, and delete calendars and events"
|
|
}
|
|
},
|
|
{
|
|
"name": "contacts:read",
|
|
"description": "Nextcloud Contacts read access",
|
|
"protocol": "openid-connect",
|
|
"attributes": {
|
|
"include.in.token.scope": "true",
|
|
"display.on.consent.screen": "true",
|
|
"consent.screen.text": "Read your contacts"
|
|
}
|
|
},
|
|
{
|
|
"name": "contacts:write",
|
|
"description": "Nextcloud Contacts write access",
|
|
"protocol": "openid-connect",
|
|
"attributes": {
|
|
"include.in.token.scope": "true",
|
|
"display.on.consent.screen": "true",
|
|
"consent.screen.text": "Create, update, and delete contacts"
|
|
}
|
|
},
|
|
{
|
|
"name": "cookbook:read",
|
|
"description": "Nextcloud Cookbook read access",
|
|
"protocol": "openid-connect",
|
|
"attributes": {
|
|
"include.in.token.scope": "true",
|
|
"display.on.consent.screen": "true",
|
|
"consent.screen.text": "Read your recipes"
|
|
}
|
|
},
|
|
{
|
|
"name": "cookbook:write",
|
|
"description": "Nextcloud Cookbook write access",
|
|
"protocol": "openid-connect",
|
|
"attributes": {
|
|
"include.in.token.scope": "true",
|
|
"display.on.consent.screen": "true",
|
|
"consent.screen.text": "Create, update, and delete recipes"
|
|
}
|
|
},
|
|
{
|
|
"name": "deck:read",
|
|
"description": "Nextcloud Deck read access",
|
|
"protocol": "openid-connect",
|
|
"attributes": {
|
|
"include.in.token.scope": "true",
|
|
"display.on.consent.screen": "true",
|
|
"consent.screen.text": "Read your boards and cards"
|
|
}
|
|
},
|
|
{
|
|
"name": "deck:write",
|
|
"description": "Nextcloud Deck write access",
|
|
"protocol": "openid-connect",
|
|
"attributes": {
|
|
"include.in.token.scope": "true",
|
|
"display.on.consent.screen": "true",
|
|
"consent.screen.text": "Create, update, and delete boards and cards"
|
|
}
|
|
},
|
|
{
|
|
"name": "tables:read",
|
|
"description": "Nextcloud Tables read access",
|
|
"protocol": "openid-connect",
|
|
"attributes": {
|
|
"include.in.token.scope": "true",
|
|
"display.on.consent.screen": "true",
|
|
"consent.screen.text": "Read your tables and rows"
|
|
}
|
|
},
|
|
{
|
|
"name": "tables:write",
|
|
"description": "Nextcloud Tables write access",
|
|
"protocol": "openid-connect",
|
|
"attributes": {
|
|
"include.in.token.scope": "true",
|
|
"display.on.consent.screen": "true",
|
|
"consent.screen.text": "Create, update, and delete tables and rows"
|
|
}
|
|
},
|
|
{
|
|
"name": "files:read",
|
|
"description": "Nextcloud Files read access",
|
|
"protocol": "openid-connect",
|
|
"attributes": {
|
|
"include.in.token.scope": "true",
|
|
"display.on.consent.screen": "true",
|
|
"consent.screen.text": "Read your files"
|
|
}
|
|
},
|
|
{
|
|
"name": "files:write",
|
|
"description": "Nextcloud Files write access",
|
|
"protocol": "openid-connect",
|
|
"attributes": {
|
|
"include.in.token.scope": "true",
|
|
"display.on.consent.screen": "true",
|
|
"consent.screen.text": "Upload, update, and delete files"
|
|
}
|
|
},
|
|
{
|
|
"name": "sharing:read",
|
|
"description": "Nextcloud Sharing read access",
|
|
"protocol": "openid-connect",
|
|
"attributes": {
|
|
"include.in.token.scope": "true",
|
|
"display.on.consent.screen": "true",
|
|
"consent.screen.text": "View shared resources"
|
|
}
|
|
},
|
|
{
|
|
"name": "sharing:write",
|
|
"description": "Nextcloud Sharing write access",
|
|
"protocol": "openid-connect",
|
|
"attributes": {
|
|
"include.in.token.scope": "true",
|
|
"display.on.consent.screen": "true",
|
|
"consent.screen.text": "Create and manage shares"
|
|
}
|
|
},
|
|
{
|
|
"name": "todo:read",
|
|
"description": "Nextcloud Tasks/Todo read access",
|
|
"protocol": "openid-connect",
|
|
"attributes": {
|
|
"include.in.token.scope": "true",
|
|
"display.on.consent.screen": "true",
|
|
"consent.screen.text": "Read your tasks"
|
|
}
|
|
},
|
|
{
|
|
"name": "todo:write",
|
|
"description": "Nextcloud Tasks/Todo write access",
|
|
"protocol": "openid-connect",
|
|
"attributes": {
|
|
"include.in.token.scope": "true",
|
|
"display.on.consent.screen": "true",
|
|
"consent.screen.text": "Create, update, and delete tasks"
|
|
}
|
|
},
|
|
{
|
|
"name": "default-audience",
|
|
"protocol": "openid-connect",
|
|
"attributes": {
|
|
"include.in.token.scope": "false",
|
|
"display.on.consent.screen": "false",
|
|
"gui.order": "",
|
|
"consent.screen.text": ""
|
|
},
|
|
"protocolMappers": [
|
|
{
|
|
"name": "mcp-server-audience",
|
|
"protocol": "openid-connect",
|
|
"protocolMapper": "oidc-audience-mapper",
|
|
"consentRequired": false,
|
|
"config": {
|
|
"included.client.audience": "nextcloud-mcp-server",
|
|
"access.token.claim": "true",
|
|
"id.token.claim": "false"
|
|
}
|
|
},
|
|
{
|
|
"name": "mcp-url-audience",
|
|
"protocol": "openid-connect",
|
|
"protocolMapper": "oidc-audience-mapper",
|
|
"consentRequired": false,
|
|
"config": {
|
|
"included.custom.audience": "http://localhost:8002",
|
|
"access.token.claim": "true",
|
|
"id.token.claim": "false"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"components": {
|
|
"org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [
|
|
{
|
|
"name": "Trusted Hosts",
|
|
"providerId": "trusted-hosts",
|
|
"subType": "anonymous",
|
|
"subComponents": {},
|
|
"config": {
|
|
"trusted-hosts": [
|
|
"localhost",
|
|
"127.0.0.1",
|
|
"172.19.0.1"
|
|
],
|
|
"host-sending-registration-request-must-match": [
|
|
"false"
|
|
],
|
|
"client-uris-must-match": [
|
|
"true"
|
|
]
|
|
}
|
|
},
|
|
{
|
|
"name": "Max Clients",
|
|
"providerId": "max-clients",
|
|
"subType": "anonymous",
|
|
"subComponents": {},
|
|
"config": {
|
|
"max-clients": [
|
|
"200"
|
|
]
|
|
}
|
|
}
|
|
]
|
|
},
|
|
"defaultDefaultClientScopes": [
|
|
"profile",
|
|
"email",
|
|
"roles",
|
|
"web-origins",
|
|
"default-audience"
|
|
],
|
|
"defaultOptionalClientScopes": [
|
|
"offline_access",
|
|
"notes:read",
|
|
"notes:write",
|
|
"calendar:read",
|
|
"calendar:write",
|
|
"contacts:read",
|
|
"contacts:write",
|
|
"cookbook:read",
|
|
"cookbook:write",
|
|
"deck:read",
|
|
"deck:write",
|
|
"tables:read",
|
|
"tables:write",
|
|
"files:read",
|
|
"files:write",
|
|
"sharing:read",
|
|
"sharing:write",
|
|
"todo:read",
|
|
"todo:write"
|
|
]
|
|
}
|