FrontMCP includes a built-in OAuth 2.1 authorization server for self-contained authentication scenarios.
The built-in login page accepts any email format without validation. Replace with a real identity provider for production use.
Basic Configuration
@ FrontMcp ({
info : { name : ' MyServer ' , version : ' 1.0.0 ' },
auth : {
mode : ' orchestrated ' ,
type : ' local ' ,
consent : { enabled : true },
},
})
export class Server {}
Configuration Options
Option Type Default Description consentConsentConfig{ enabled: false }Consent UI configuration sessionMode'stateful' | 'stateless''stateful'Session management strategy tokenStorageobject{ type: 'memory' }Token storage backend allowDefaultPublicbooleanfalseAllow unauthenticated access anonymousScopesstring[]['anonymous']Scopes for anonymous sessions incrementalAuthIncrementalAuthConfig{ enabled: true }Progressive authorization config
OAuth Endpoints
Local mode exposes standard OAuth 2.1 endpoints:
Endpoint Method Description /oauth/authorizeGET Start authorization flow /oauth/tokenPOST Exchange code for tokens /oauth/registerPOST Dynamic Client Registration /oauth/userinfoGET Get user profile /.well-known/oauth-authorization-serverGET Server metadata /.well-known/jwks.jsonGET Public signing keys
Authorization Request
GET /oauth/authorize
?response_type=code
&client_id=your-client-id
&redirect_uri=http://localhost:3000/callback
&scope=openid profile
&state=random-state
&code_challenge=base64url(sha256(verifier))
&code_challenge_method=S256
Token Exchange
POST /oauth/token
Content-Type: application/x-www-form-urlencoded
grant_type = authorization_code
& code = authorization-code
& redirect_uri = http://localhost:3000/callback
& client_id = your-client-id
& code_verifier = original-verifier
Key Management
Auto-Generated Keys
By default, FrontMCP generates RS256 keys at startup:
auth : {
mode : ' orchestrated ' ,
type : ' local ' ,
// Keys auto-generated
}
Auto-generated keys are lost on restart. Existing tokens become invalid.
Persistent Keys
Provide keys for stable token validation:
auth : {
mode : ' orchestrated ' ,
type : ' local ' ,
local : {
signKey : {
kty : ' RSA ' ,
kid : ' my-key-id ' ,
alg : ' RS256 ' ,
n : ' ... ' , // RSA modulus
e : ' AQAB ' ,
d : ' ... ' , // Private exponent
// ... other JWK parameters
},
},
}
ES256 Keys
Use ES256 for smaller tokens:
auth : {
mode : ' orchestrated ' ,
type : ' local ' ,
local : {
signKey : {
kty : ' EC ' ,
crv : ' P-256 ' ,
x : ' ... ' ,
y : ' ... ' ,
d : ' ... ' ,
},
},
}
Dynamic Client Registration
DCR allows clients to register programmatically. DCR is enabled by default in development.
Registration Request
POST /oauth/register
Content-Type: application/json
{
"redirect_uris" : [ " http://localhost:3000/callback " ],
"client_name" : " My Application " ,
"token_endpoint_auth_method" : " none " ,
"grant_types" : [ " authorization_code " , " refresh_token " ],
"response_types" : [ " code " ]
}
Registration Response
{
" client_id " : " generated-uuid " ,
" client_id_issued_at " : 1234567890 ,
" redirect_uris " : [ " http://localhost:3000/callback " ],
" client_name " : " My Application " ,
" token_endpoint_auth_method " : " none " ,
" grant_types " : [ " authorization_code " , " refresh_token " ],
" response_types " : [ " code " ]
}
DCR is intended for development only. In production, pre-register clients. DCR only allows localhost redirect URIs by default.
Per-App Configuration
Configure local auth per app with splitByApp: true:
@ App ({
name : ' Billing ' ,
auth : {
mode : ' orchestrated ' ,
type : ' local ' ,
consent : { enabled : true },
},
})
export class BillingApp {}
@ App ({
name : ' Analytics ' ,
auth : {
mode : ' orchestrated ' ,
type : ' local ' ,
},
})
export class AnalyticsApp {}
@ FrontMcp ({
info : { name : ' Suite ' , version : ' 1.0.0 ' },
apps : [ BillingApp , AnalyticsApp ],
splitByApp : true ,
})
export class Server {}
Token Storage
In-Memory (Development)
auth : {
mode : ' orchestrated ' ,
type : ' local ' ,
tokenStorage : { type : ' memory ' },
}
Redis (Production)
auth : {
mode : ' orchestrated ' ,
type : ' local ' ,
tokenStorage : {
type : ' redis ' ,
config : {
host : process . env . REDIS_HOST !,
port : parseInt ( process . env . REDIS_PORT || ' 6379 ' ),
password : process . env . REDIS_PASSWORD ,
keyPrefix : ' myapp:auth: ' ,
},
},
}
Consent Configuration
Enable and customize the consent UI:
auth : {
mode : ' orchestrated ' ,
type : ' local ' ,
consent : {
enabled : true ,
groupByApp : true , // Group tools by app
showDescriptions : true , // Show tool descriptions
allowSelectAll : true , // Allow selecting all tools
requireSelection : true , // Require at least one tool
rememberConsent : true , // Remember for future sessions
excludedTools : [ ' health ' ], // Always available tools
defaultSelectedTools : [], // Pre-selected tools
customMessage : ' Select the tools you want to grant access to. ' ,
},
}
Complete Example
import { FrontMcp } from ' @frontmcp/sdk ' ;
@ FrontMcp ({
info : { name : ' MyServer ' , version : ' 1.0.0 ' },
auth : {
mode : ' orchestrated ' ,
type : ' local ' ,
consent : { enabled : true },
sessionMode : ' stateful ' ,
tokenStorage : {
type : ' redis ' ,
config : {
host : process . env . REDIS_HOST !,
port : parseInt ( process . env . REDIS_PORT || ' 6379 ' ),
password : process . env . REDIS_PASSWORD ,
},
},
refresh : {
enabled : true ,
skewSeconds : 60 ,
},
local : {
signKey : JSON . parse ( process . env . JWT_SIGNING_KEY !),
},
incrementalAuth : {
enabled : true ,
allowSkip : true ,
skippedAppBehavior : ' require-auth ' ,
},
},
})
export class Server {}
Troubleshooting
Tokens invalid after restart
Auto-generated keys are lost on restart. Either:
Provide persistent keys via local.signKey
Use Redis for token storage
Accept that users must re-authenticate
Ensure you’re using S256 challenge method and the code_verifier matches the original code_challenge.
Session not found across instances
When running multiple server instances, use Redis for token storage to share session state.
Next Steps