mcp-auth 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +43 -0
- data/CONTRIBUTING.md +107 -0
- data/LICENSE.txt +21 -0
- data/README.md +869 -0
- data/Rakefile +8 -0
- data/app/controllers/mcp/auth/oauth_controller.rb +494 -0
- data/app/controllers/mcp/auth/well_known_controller.rb +147 -0
- data/app/models/mcp/auth/access_token.rb +30 -0
- data/app/models/mcp/auth/authorization_code.rb +33 -0
- data/app/models/mcp/auth/oauth_client.rb +60 -0
- data/app/models/mcp/auth/refresh_token.rb +32 -0
- data/app/views/mcp/auth/consent.html.erb +527 -0
- data/config/routes.rb +43 -0
- data/lib/generators/mcp/auth/install_generator.rb +80 -0
- data/lib/generators/mcp/auth/templates/README +114 -0
- data/lib/generators/mcp/auth/templates/create_access_tokens.rb.erb +23 -0
- data/lib/generators/mcp/auth/templates/create_authorization_codes.rb.erb +26 -0
- data/lib/generators/mcp/auth/templates/create_oauth_clients.rb.erb +22 -0
- data/lib/generators/mcp/auth/templates/create_refresh_tokens.rb.erb +22 -0
- data/lib/generators/mcp/auth/templates/initializer.rb +199 -0
- data/lib/generators/mcp/auth/templates/views/consent.html.erb +527 -0
- data/lib/mcp/auth/engine.rb +32 -0
- data/lib/mcp/auth/scope_registry.rb +113 -0
- data/lib/mcp/auth/services/authorization_service.rb +102 -0
- data/lib/mcp/auth/services/token_service.rb +230 -0
- data/lib/mcp/auth/version.rb +7 -0
- data/lib/mcp/auth.rb +109 -0
- data/lib/tasks/mcp_auth_tasks.rake +89 -0
- metadata +254 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails/generators'
|
|
4
|
+
require 'rails/generators/active_record'
|
|
5
|
+
|
|
6
|
+
module Mcp
|
|
7
|
+
module Auth
|
|
8
|
+
module Generators
|
|
9
|
+
class InstallGenerator < Rails::Generators::Base
|
|
10
|
+
include ActiveRecord::Generators::Migration
|
|
11
|
+
|
|
12
|
+
source_root File.expand_path('templates', __dir__)
|
|
13
|
+
|
|
14
|
+
desc "Generates MCP Auth migrations, initializer, and views"
|
|
15
|
+
|
|
16
|
+
def copy_migrations
|
|
17
|
+
migration_template "create_oauth_clients.rb.erb",
|
|
18
|
+
"db/migrate/create_mcp_auth_oauth_clients.rb",
|
|
19
|
+
migration_version: migration_version
|
|
20
|
+
|
|
21
|
+
migration_template "create_authorization_codes.rb.erb",
|
|
22
|
+
"db/migrate/create_mcp_auth_authorization_codes.rb",
|
|
23
|
+
migration_version: migration_version
|
|
24
|
+
|
|
25
|
+
migration_template "create_access_tokens.rb.erb",
|
|
26
|
+
"db/migrate/create_mcp_auth_access_tokens.rb",
|
|
27
|
+
migration_version: migration_version
|
|
28
|
+
|
|
29
|
+
migration_template "create_refresh_tokens.rb.erb",
|
|
30
|
+
"db/migrate/create_mcp_auth_refresh_tokens.rb",
|
|
31
|
+
migration_version: migration_version
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def copy_initializer
|
|
35
|
+
template "initializer.rb", "config/initializers/mcp_auth.rb"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def copy_views
|
|
39
|
+
# Create the directory first
|
|
40
|
+
empty_directory "app/views/mcp/auth"
|
|
41
|
+
|
|
42
|
+
# Copy consent view template
|
|
43
|
+
template "views/consent.html.erb", "app/views/mcp/auth/consent.html.erb"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def show_readme
|
|
47
|
+
if File.exist?(File.join(self.class.source_root, "README"))
|
|
48
|
+
readme "README"
|
|
49
|
+
end
|
|
50
|
+
rescue Thor::Error
|
|
51
|
+
# Skip silently
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def show_post_install_message
|
|
55
|
+
say "\n" + "="*80
|
|
56
|
+
say "MCP Auth has been installed!", :green
|
|
57
|
+
say "="*80
|
|
58
|
+
say "\nFiles created:"
|
|
59
|
+
say " - db/migrate/*_create_mcp_auth_*.rb (4 migrations)"
|
|
60
|
+
say " - config/initializers/mcp_auth.rb"
|
|
61
|
+
say " - app/views/mcp/auth/consent.html.erb"
|
|
62
|
+
say "\nNext steps:"
|
|
63
|
+
say "1. Run migrations: rails db:migrate"
|
|
64
|
+
say "2. Configure: config/initializers/mcp_auth.rb"
|
|
65
|
+
say "3. Customize consent view: app/views/mcp/auth/consent.html.erb"
|
|
66
|
+
say "4. Mount routes in config/routes.rb (if not already done):"
|
|
67
|
+
say " mount Mcp::Auth::Engine => '/'"
|
|
68
|
+
say "\nDocumentation: https://github.com/SerhiiBorozenets/mcp-auth"
|
|
69
|
+
say "="*80 + "\n"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
private
|
|
73
|
+
|
|
74
|
+
def migration_version
|
|
75
|
+
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
===============================================================================
|
|
2
|
+
|
|
3
|
+
MCP Auth has been installed!
|
|
4
|
+
|
|
5
|
+
Next steps:
|
|
6
|
+
|
|
7
|
+
1. Run the migrations:
|
|
8
|
+
|
|
9
|
+
rails db:migrate
|
|
10
|
+
|
|
11
|
+
2. Configure the initializer at config/initializers/mcp_auth.rb
|
|
12
|
+
|
|
13
|
+
Set your OAuth secret and customize user data fetching.
|
|
14
|
+
|
|
15
|
+
3. Ensure your ApplicationController has authentication methods:
|
|
16
|
+
|
|
17
|
+
- current_user: returns the currently signed-in user
|
|
18
|
+
- current_org: returns the current organization (optional)
|
|
19
|
+
- user_signed_in?: returns true if user is signed in
|
|
20
|
+
|
|
21
|
+
4. Set environment variables (optional):
|
|
22
|
+
|
|
23
|
+
MCP_HMAC_SECRET: Secret key for signing JWTs
|
|
24
|
+
MCP_AUTHORIZATION_SERVER_URL: Custom authorization server URL
|
|
25
|
+
|
|
26
|
+
5. Your OAuth endpoints are now available at:
|
|
27
|
+
|
|
28
|
+
- /.well-known/oauth-protected-resource (Protected Resource Metadata)
|
|
29
|
+
- /.well-known/oauth-authorization-server (Authorization Server Metadata)
|
|
30
|
+
- /oauth/authorize (Authorization endpoint)
|
|
31
|
+
- /oauth/token (Token endpoint)
|
|
32
|
+
- /oauth/register (Dynamic client registration)
|
|
33
|
+
- /oauth/revoke (Token revocation)
|
|
34
|
+
- /oauth/introspect (Token introspection)
|
|
35
|
+
|
|
36
|
+
6. Mount the routes in your config/routes.rb:
|
|
37
|
+
|
|
38
|
+
Rails.application.routes.draw do
|
|
39
|
+
# Mount MCP Auth routes at the top
|
|
40
|
+
mount Mcp::Auth::Engine => "/"
|
|
41
|
+
|
|
42
|
+
# ... your other routes
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
CUSTOMIZING THE CONSENT SCREEN
|
|
46
|
+
-------------------------------
|
|
47
|
+
|
|
48
|
+
The generator has created a default consent view at:
|
|
49
|
+
app/views/mcp/auth/consent.html.erb
|
|
50
|
+
|
|
51
|
+
To use your custom consent view:
|
|
52
|
+
|
|
53
|
+
1. Edit config/initializers/mcp_auth.rb and set:
|
|
54
|
+
config.use_custom_consent_view = true
|
|
55
|
+
|
|
56
|
+
2. Customize app/views/mcp/auth/consent.html.erb to match your branding
|
|
57
|
+
|
|
58
|
+
3. Available instance variables in the view:
|
|
59
|
+
@client_name - Name of the OAuth client requesting access
|
|
60
|
+
@requested_scopes - Array of human-readable permission descriptions
|
|
61
|
+
@authorization_params - Hash containing OAuth flow parameters
|
|
62
|
+
|
|
63
|
+
4. The form must POST to oauth_approve_path with:
|
|
64
|
+
- All @authorization_params as hidden fields
|
|
65
|
+
- A button with name="approved" value="true" for approval
|
|
66
|
+
- A button with name="approved" value="false" for denial
|
|
67
|
+
|
|
68
|
+
Example form:
|
|
69
|
+
<%= form_with url: oauth_approve_path, method: :post do |f| %>
|
|
70
|
+
<% @authorization_params.each do |key, value| %>
|
|
71
|
+
<%= f.hidden_field key, value: value, id: nil %>
|
|
72
|
+
<% end %>
|
|
73
|
+
<%= f.button 'Deny', name: 'approved', value: 'false' %>
|
|
74
|
+
<%= f.button 'Authorize', name: 'approved', value: 'true' %>
|
|
75
|
+
<% end %>
|
|
76
|
+
|
|
77
|
+
TESTING THE OAUTH FLOW
|
|
78
|
+
-----------------------
|
|
79
|
+
|
|
80
|
+
1. Start your Rails server:
|
|
81
|
+
rails server
|
|
82
|
+
|
|
83
|
+
2. Test the discovery endpoints:
|
|
84
|
+
curl http://localhost:3000/.well-known/oauth-protected-resource
|
|
85
|
+
curl http://localhost:3000/.well-known/oauth-authorization-server
|
|
86
|
+
|
|
87
|
+
3. Register a test client:
|
|
88
|
+
curl -X POST http://localhost:3000/oauth/register \
|
|
89
|
+
-H "Content-Type: application/json" \
|
|
90
|
+
-d '{
|
|
91
|
+
"client_name": "Test Client",
|
|
92
|
+
"redirect_uris": ["http://localhost:3000/callback"]
|
|
93
|
+
}'
|
|
94
|
+
|
|
95
|
+
4. Use the returned client_id and client_secret for OAuth flow
|
|
96
|
+
|
|
97
|
+
RAKE TASKS
|
|
98
|
+
----------
|
|
99
|
+
|
|
100
|
+
Clean up expired tokens:
|
|
101
|
+
rake mcp_auth:cleanup
|
|
102
|
+
|
|
103
|
+
Show statistics:
|
|
104
|
+
rake mcp_auth:stats
|
|
105
|
+
|
|
106
|
+
Revoke tokens for a client:
|
|
107
|
+
rake mcp_auth:revoke_client_tokens[CLIENT_ID]
|
|
108
|
+
|
|
109
|
+
Revoke tokens for a user:
|
|
110
|
+
rake mcp_auth:revoke_user_tokens[USER_ID]
|
|
111
|
+
|
|
112
|
+
For more information, see: https://github.com/SerhiiBorozenets/mcp-auth
|
|
113
|
+
|
|
114
|
+
===============================================================================
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
class CreateMcpAuthAccessTokens < ActiveRecord::Migration<%= migration_version %>
|
|
2
|
+
def up
|
|
3
|
+
create_table :mcp_auth_access_tokens do |t|
|
|
4
|
+
t.string :token, null: false, index: { unique: true }
|
|
5
|
+
t.string :client_id, null: false
|
|
6
|
+
t.string :resource
|
|
7
|
+
t.string :scope
|
|
8
|
+
t.references :user, foreign_key: true
|
|
9
|
+
t.references :org, foreign_key: true, null: true
|
|
10
|
+
t.datetime :expires_at, null: false
|
|
11
|
+
t.timestamps
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
add_index :mcp_auth_access_tokens, :client_id
|
|
15
|
+
add_index :mcp_auth_access_tokens, :expires_at
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def down
|
|
19
|
+
remove_index :mcp_auth_access_tokens, :client_id
|
|
20
|
+
remove_index :mcp_auth_access_tokens, :expires_at
|
|
21
|
+
drop_table :mcp_auth_access_tokens
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
class CreateMcpAuthAuthorizationCodes < ActiveRecord::Migration<%= migration_version %>
|
|
2
|
+
def up
|
|
3
|
+
create_table :mcp_auth_authorization_codes do |t|
|
|
4
|
+
t.string :code, null: false, index: { unique: true }
|
|
5
|
+
t.string :client_id, null: false
|
|
6
|
+
t.string :redirect_uri, null: false
|
|
7
|
+
t.string :code_challenge
|
|
8
|
+
t.string :code_challenge_method
|
|
9
|
+
t.string :resource
|
|
10
|
+
t.string :scope
|
|
11
|
+
t.references :user, foreign_key: true
|
|
12
|
+
t.references :org, foreign_key: true, null: true
|
|
13
|
+
t.datetime :expires_at, null: false
|
|
14
|
+
t.timestamps
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
add_index :mcp_auth_authorization_codes, :client_id
|
|
18
|
+
add_index :mcp_auth_authorization_codes, :expires_at
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def down
|
|
22
|
+
remove_index :mcp_auth_authorization_codes, :client_id
|
|
23
|
+
remove_index :mcp_auth_authorization_codes, :expires_at
|
|
24
|
+
drop_table :mcp_auth_authorization_codes
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
class CreateMcpAuthOauthClients < ActiveRecord::Migration<%= migration_version %>
|
|
2
|
+
def up
|
|
3
|
+
create_table :mcp_auth_oauth_clients, id: false do |t|
|
|
4
|
+
t.uuid :client_id, primary_key: true, null: false, default: -> { 'gen_random_uuid()' }
|
|
5
|
+
t.string :client_secret, null: false
|
|
6
|
+
t.text :redirect_uris
|
|
7
|
+
t.text :grant_types
|
|
8
|
+
t.text :response_types
|
|
9
|
+
t.string :scope
|
|
10
|
+
t.string :client_name
|
|
11
|
+
t.string :client_uri
|
|
12
|
+
t.timestamps
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
add_index :mcp_auth_oauth_clients, :client_id, unique: true
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def down
|
|
19
|
+
remove_index :mcp_auth_oauth_clients, :client_id
|
|
20
|
+
drop_table :mcp_auth_oauth_clients
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
class CreateMcpAuthRefreshTokens < ActiveRecord::Migration<%= migration_version %>
|
|
2
|
+
def up
|
|
3
|
+
create_table :mcp_auth_refresh_tokens do |t|
|
|
4
|
+
t.string :token, null: false, index: { unique: true }
|
|
5
|
+
t.string :client_id, null: false
|
|
6
|
+
t.string :scope
|
|
7
|
+
t.references :user, foreign_key: true
|
|
8
|
+
t.references :org, foreign_key: true, null: true
|
|
9
|
+
t.datetime :expires_at, null: false
|
|
10
|
+
t.timestamps
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
add_index :mcp_auth_refresh_tokens, :client_id
|
|
14
|
+
add_index :mcp_auth_refresh_tokens, :expires_at
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def down
|
|
18
|
+
remove_index :mcp_auth_refresh_tokens, :client_id
|
|
19
|
+
remove_index :mcp_auth_refresh_tokens, :expires_at
|
|
20
|
+
drop_table :mcp_auth_refresh_tokens
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Mcp::Auth.configure do |config|
|
|
4
|
+
# ============================================================================
|
|
5
|
+
# OAUTH CONFIGURATION
|
|
6
|
+
# ============================================================================
|
|
7
|
+
|
|
8
|
+
# OAuth secret for signing JWTs
|
|
9
|
+
# Should be a secure random string in production (use: rails secret)
|
|
10
|
+
config.oauth_secret = ENV.fetch('MCP_HMAC_SECRET', Rails.application.secret_key_base)
|
|
11
|
+
|
|
12
|
+
# Authorization server URL (optional - defaults to same as resource server)
|
|
13
|
+
# Set this if you're using a separate authorization server
|
|
14
|
+
# Example: config.authorization_server_url = 'https://auth.example.com'
|
|
15
|
+
config.authorization_server_url = ENV.fetch('MCP_AUTHORIZATION_SERVER_URL', nil)
|
|
16
|
+
|
|
17
|
+
# ============================================================================
|
|
18
|
+
# MCP SERVER CONFIGURATION
|
|
19
|
+
# ============================================================================
|
|
20
|
+
|
|
21
|
+
# MCP Server Path - where your MCP server is mounted
|
|
22
|
+
# This MUST match the path where you mount FastMCP or your MCP server
|
|
23
|
+
# Default: '/mcp'
|
|
24
|
+
# Examples: '/api/mcp', '/v1/assistant', '/assistant/api'
|
|
25
|
+
config.mcp_server_path = ENV.fetch('MCP_SERVER_PATH', '/mcp')
|
|
26
|
+
|
|
27
|
+
# MCP Documentation URL - link to your MCP server documentation
|
|
28
|
+
# Can be a full URL (https://docs.example.com/mcp) or a path (/docs/mcp)
|
|
29
|
+
# Default: nil (will auto-generate as {mcp_server_path}/docs)
|
|
30
|
+
# Examples:
|
|
31
|
+
# config.mcp_docs_url = '/docs/mcp-api'
|
|
32
|
+
# config.mcp_docs_url = 'https://docs.example.com/mcp-api'
|
|
33
|
+
config.mcp_docs_url = ENV.fetch('MCP_DOCS_URL', nil)
|
|
34
|
+
|
|
35
|
+
# ============================================================================
|
|
36
|
+
# TOKEN LIFETIMES (in seconds)
|
|
37
|
+
# ============================================================================
|
|
38
|
+
|
|
39
|
+
config.access_token_lifetime = 3600 # 1 hour
|
|
40
|
+
config.refresh_token_lifetime = 2_592_000 # 30 days
|
|
41
|
+
config.authorization_code_lifetime = 1800 # 30 minutes
|
|
42
|
+
|
|
43
|
+
# ============================================================================
|
|
44
|
+
# USER DATA FETCHER
|
|
45
|
+
# ============================================================================
|
|
46
|
+
|
|
47
|
+
# This proc is called when generating tokens to fetch user-specific data
|
|
48
|
+
# Customize this based on your application's user and organization models
|
|
49
|
+
#
|
|
50
|
+
# Expected return value: Hash with keys:
|
|
51
|
+
# - :email (String) - User's email address
|
|
52
|
+
# - :api_key_id (String/Integer, optional) - API key ID if using API keys
|
|
53
|
+
# - :api_key_secret (String, optional) - API key secret if using API keys
|
|
54
|
+
config.fetch_user_data = proc do |data|
|
|
55
|
+
user = User.find(data[:user_id])
|
|
56
|
+
|
|
57
|
+
# Example: If you have API keys per organization user
|
|
58
|
+
# org_user = OrgUser.find_by(user_id: data[:user_id], org_id: data[:org_id])
|
|
59
|
+
# api_key = org_user&.api_key
|
|
60
|
+
|
|
61
|
+
{
|
|
62
|
+
email: user.email,
|
|
63
|
+
api_key_id: nil, # Set to your API key ID if applicable
|
|
64
|
+
api_key_secret: nil # Set to your API key secret if applicable
|
|
65
|
+
}
|
|
66
|
+
rescue ActiveRecord::RecordNotFound
|
|
67
|
+
{ email: 'unknown@example.com', api_key_id: nil, api_key_secret: nil }
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# ============================================================================
|
|
71
|
+
# AUTHENTICATION METHODS
|
|
72
|
+
# ============================================================================
|
|
73
|
+
|
|
74
|
+
# Methods used to get current user and organization in your controllers
|
|
75
|
+
# Change these if you use different method names (e.g., authenticated_user)
|
|
76
|
+
config.current_user_method = :current_user
|
|
77
|
+
config.current_org_method = :current_org
|
|
78
|
+
|
|
79
|
+
# ============================================================================
|
|
80
|
+
# SCOPE CONFIGURATION
|
|
81
|
+
# ============================================================================
|
|
82
|
+
|
|
83
|
+
# Register scopes that your application needs:
|
|
84
|
+
#
|
|
85
|
+
# Syntax:
|
|
86
|
+
# config.register_scope 'scope_key',
|
|
87
|
+
# name: 'Display Name',
|
|
88
|
+
# description: 'What this scope allows (shown to users)',
|
|
89
|
+
# required: false # Set to true if scope is always required
|
|
90
|
+
#
|
|
91
|
+
# IMPORTANT: At least one scope should be registered for OAuth to work properly.
|
|
92
|
+
|
|
93
|
+
# Basic read access - typically required
|
|
94
|
+
config.register_scope 'mcp:read',
|
|
95
|
+
name: 'Read Access',
|
|
96
|
+
description: 'Read your data and resources',
|
|
97
|
+
required: true # Usually required for MCP to function
|
|
98
|
+
|
|
99
|
+
# Write access - allows modifications
|
|
100
|
+
config.register_scope 'mcp:write',
|
|
101
|
+
name: 'Write Access',
|
|
102
|
+
description: 'Create and modify data on your behalf',
|
|
103
|
+
required: false
|
|
104
|
+
|
|
105
|
+
# Execute tools and automated actions
|
|
106
|
+
# config.register_scope 'mcp:tools',
|
|
107
|
+
# name: 'Execute Tools',
|
|
108
|
+
# description: 'Run tools and perform automated actions in your account'
|
|
109
|
+
|
|
110
|
+
# Analytics and reporting
|
|
111
|
+
# config.register_scope 'mcp:analytics',
|
|
112
|
+
# name: 'Analytics Access',
|
|
113
|
+
# description: 'View analytics dashboards, charts, and reports'
|
|
114
|
+
|
|
115
|
+
# Data export capabilities
|
|
116
|
+
# config.register_scope 'mcp:export',
|
|
117
|
+
# name: 'Data Export',
|
|
118
|
+
# description: 'Export data in CSV, PDF, and Excel formats'
|
|
119
|
+
|
|
120
|
+
# Administrative access
|
|
121
|
+
# config.register_scope 'mcp:admin',
|
|
122
|
+
# name: 'Administrative Access',
|
|
123
|
+
# description: 'Manage settings, users, and perform administrative actions',
|
|
124
|
+
# required: false
|
|
125
|
+
|
|
126
|
+
# Custom application-specific scopes
|
|
127
|
+
# config.register_scope 'mcp:orders',
|
|
128
|
+
# name: 'Order Management',
|
|
129
|
+
# description: 'View and manage customer orders'
|
|
130
|
+
|
|
131
|
+
# config.register_scope 'mcp:notifications',
|
|
132
|
+
# name: 'Send Notifications',
|
|
133
|
+
# description: 'Send notifications and messages on your behalf'
|
|
134
|
+
|
|
135
|
+
# ============================================================================
|
|
136
|
+
# SCOPE VALIDATION (OPTIONAL)
|
|
137
|
+
# ============================================================================
|
|
138
|
+
|
|
139
|
+
# Validate which scopes users can approve based on their roles/permissions
|
|
140
|
+
# This callback is called for each requested scope during authorization
|
|
141
|
+
#
|
|
142
|
+
# Parameters:
|
|
143
|
+
# - user: Current user object
|
|
144
|
+
# - org: Current organization object (may be nil)
|
|
145
|
+
# - scope: Scope being requested (String)
|
|
146
|
+
#
|
|
147
|
+
# Return:
|
|
148
|
+
# - true: User can approve this scope
|
|
149
|
+
# - false: User cannot approve this scope (will be filtered out)
|
|
150
|
+
#
|
|
151
|
+
# Example: Restrict admin scope to admin users only
|
|
152
|
+
# config.validate_scope_for_user = proc do |user, org, scope|
|
|
153
|
+
# case scope
|
|
154
|
+
# when 'mcp:admin'
|
|
155
|
+
# # Only admins can approve admin scope
|
|
156
|
+
# user.admin? || org&.admins&.include?(user)
|
|
157
|
+
# when 'mcp:analytics'
|
|
158
|
+
# # Check if user has analytics permission
|
|
159
|
+
# user.has_permission?(:view_analytics)
|
|
160
|
+
# when 'mcp:export'
|
|
161
|
+
# # Check if organization plan includes export
|
|
162
|
+
# org&.plan&.includes_export?
|
|
163
|
+
# else
|
|
164
|
+
# true # Allow all other scopes
|
|
165
|
+
# end
|
|
166
|
+
# end
|
|
167
|
+
|
|
168
|
+
# ============================================================================
|
|
169
|
+
# CUSTOM CONSENT VIEW (OPTIONAL)
|
|
170
|
+
# ============================================================================
|
|
171
|
+
|
|
172
|
+
# Set to true to use your own consent view instead of the gem's default
|
|
173
|
+
# The view will be at app/views/mcp/auth/consent.html.erb
|
|
174
|
+
config.use_custom_consent_view = false
|
|
175
|
+
|
|
176
|
+
# Path to custom consent view (relative to app/views)
|
|
177
|
+
# Only used if use_custom_consent_view is true
|
|
178
|
+
config.consent_view_path = 'mcp/auth/consent'
|
|
179
|
+
|
|
180
|
+
# To customize the consent screen:
|
|
181
|
+
# 1. Set use_custom_consent_view = true
|
|
182
|
+
# 2. Copy the default view from the gem or generate it:
|
|
183
|
+
# rails generate mcp:auth:install
|
|
184
|
+
# 3. Edit app/views/mcp/auth/consent.html.erb
|
|
185
|
+
# 4. The view has access to these instance variables:
|
|
186
|
+
# - @client_name: Name of the OAuth client requesting access
|
|
187
|
+
# - @requested_scopes: Array of scope hashes with keys:
|
|
188
|
+
# * :key - Scope identifier (e.g., 'mcp:read')
|
|
189
|
+
# * :name - Human-readable name (e.g., 'Read Access')
|
|
190
|
+
# * :description - What the scope allows
|
|
191
|
+
# * :required - Whether scope is required (true/false)
|
|
192
|
+
# * :pre_selected - Whether scope was in the original request
|
|
193
|
+
# - @authorization_params: Hash of OAuth parameters to preserve
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# Include controller helpers in ApplicationController
|
|
197
|
+
Rails.application.config.to_prepare do
|
|
198
|
+
ApplicationController.include Mcp::Auth::ControllerHelpers
|
|
199
|
+
end
|