standard_id-apple 0.1.1 → 0.2.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 +4 -4
- data/.ruby-version +1 -1
- data/CHANGELOG.md +28 -1
- data/CLAUDE.md +26 -0
- data/lib/standard_id/apple/providers/apple.rb +30 -16
- data/lib/standard_id/apple/railtie.rb +13 -0
- data/lib/standard_id/apple/version.rb +1 -1
- data/lib/standard_id/apple.rb +1 -0
- metadata +5 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 12a977e4ff2079df4c467f77c117bd3ea4564de05381b29514f7c1bbdec87380
|
|
4
|
+
data.tar.gz: c071fe2549d4dae82f12d98e435214a615e68fa892fd85ff2a0dda88290c1a9b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c94b517719fa7da262ec4c189e4c3d791eef9e3e352afc4181844f0d353729bf167523932d9aab1c1eae88825001d9e87a7cf0c808b14182a6c081190ab956a3
|
|
7
|
+
data.tar.gz: b92eb9d4c48fefc7c59e1636f28e8a5483e13e58bdc83753716ca6e4956d334b8880e2a685a4288949b13c5048b433b788db0c874df9d2fd25809ae6b287e847
|
data/.ruby-version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
4.0.1
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
1
8
|
## [Unreleased]
|
|
2
9
|
|
|
10
|
+
## [0.2.0] - 2026-04-21
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Auto-register provider with StandardId via `Rails::Railtie` on `config.after_initialize`, so apps that bundle the gem no longer need an explicit initializer (#30)
|
|
15
|
+
|
|
16
|
+
## [0.1.2] - 2026-01-13
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- Support nonce and passing custom parameters to Apple Sign In (#2)
|
|
21
|
+
|
|
22
|
+
## [0.1.1] - 2025-12-24
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- Standardized config access patterns
|
|
27
|
+
|
|
3
28
|
## [0.1.0] - 2025-12-20
|
|
4
29
|
|
|
5
|
-
|
|
30
|
+
### Added
|
|
31
|
+
|
|
32
|
+
- Initial release of Apple Sign In provider plugin for StandardId
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
## Worktree-Only Workflow (Enforced)
|
|
4
|
+
|
|
5
|
+
**All file modifications are blocked in the main checkout.** A PreToolUse hook (`enforce-worktree.sh`) rejects Edit, Write, and NotebookEdit operations targeting files outside a worktree. There are no opt-outs. Do not use Bash to write files in the main checkout either (e.g., `echo >`, `sed -i`, `tee`, `cp`) — the hook cannot intercept shell commands, so this rule is instruction-enforced.
|
|
6
|
+
|
|
7
|
+
Before writing any code, create a worktree:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
DEFAULT_BRANCH=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@refs/remotes/origin/@@')
|
|
11
|
+
DEFAULT_BRANCH=${DEFAULT_BRANCH:-main}
|
|
12
|
+
git fetch origin "$DEFAULT_BRANCH"
|
|
13
|
+
git worktree add .worktrees/<name> -b <branch-name> "origin/$DEFAULT_BRANCH"
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Then work inside `.worktrees/<name>/` for the rest of the session.
|
|
17
|
+
|
|
18
|
+
**Naming:** Use the Linear issue identifier if available (e.g., `.worktrees/<identifier>`), a task slug (e.g., `.worktrees/fix-auth-timeout`), or today's date (e.g., `.worktrees/2026-04-01`) as fallback.
|
|
19
|
+
|
|
20
|
+
**The hook allows modifications only when:**
|
|
21
|
+
|
|
22
|
+
1. The file is inside a git worktree (detected via `git rev-parse --git-dir` returning a path under `.git/worktrees/`)
|
|
23
|
+
2. Running in a CI/automated context where the checkout is already isolated
|
|
24
|
+
**Why this matters:** Working directly on the main checkout causes cross-contamination between sessions — uncommitted changes, wrong branches, and dirty state leak into unrelated work. Worktrees eliminate this entirely.
|
|
25
|
+
|
|
26
|
+
See the `/worktree` and `/start` skills for full conventions and flags.
|
|
@@ -12,40 +12,47 @@ module StandardId
|
|
|
12
12
|
JWKS_URI = "#{ISSUER}/auth/keys".freeze
|
|
13
13
|
DEFAULT_SCOPE = "name email".freeze
|
|
14
14
|
DEFAULT_RESPONSE_MODE = "form_post".freeze
|
|
15
|
+
AUTHORIZATION_PARAM_DEFAULTS = {
|
|
16
|
+
scope: DEFAULT_SCOPE,
|
|
17
|
+
response_mode: DEFAULT_RESPONSE_MODE
|
|
18
|
+
}.freeze
|
|
15
19
|
|
|
16
20
|
class << self
|
|
17
21
|
def provider_name
|
|
18
22
|
"apple"
|
|
19
23
|
end
|
|
20
24
|
|
|
21
|
-
def
|
|
22
|
-
scope
|
|
23
|
-
|
|
25
|
+
def supported_authorization_params
|
|
26
|
+
[:nonce, :scope, :response_mode]
|
|
27
|
+
end
|
|
24
28
|
|
|
29
|
+
def authorization_url(state:, redirect_uri:, **options)
|
|
25
30
|
ensure_basic_credentials!
|
|
26
31
|
|
|
27
32
|
query = {
|
|
28
33
|
client_id: StandardId.config.apple_client_id,
|
|
29
|
-
redirect_uri
|
|
34
|
+
redirect_uri:,
|
|
30
35
|
response_type: "code",
|
|
31
|
-
|
|
32
|
-
response_mode: response_mode,
|
|
33
|
-
state: state
|
|
36
|
+
state:
|
|
34
37
|
}
|
|
35
38
|
|
|
36
|
-
|
|
39
|
+
supported_authorization_params.each do |param|
|
|
40
|
+
query[param] = options[param] || AUTHORIZATION_PARAM_DEFAULTS[param]
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
"#{AUTH_ENDPOINT}?#{URI.encode_www_form(query.compact)}"
|
|
37
44
|
end
|
|
38
45
|
|
|
39
|
-
def get_user_info(code: nil, id_token: nil, access_token: nil, redirect_uri: nil, **options)
|
|
46
|
+
def get_user_info(code: nil, id_token: nil, access_token: nil, redirect_uri: nil, nonce: nil, **options)
|
|
40
47
|
client_id = options[:client_id] || StandardId.config.apple_client_id
|
|
41
48
|
|
|
42
49
|
if id_token.present?
|
|
43
50
|
build_response(
|
|
44
|
-
verify_id_token(id_token: id_token, client_id: client_id),
|
|
51
|
+
verify_id_token(id_token: id_token, client_id: client_id, nonce: nonce),
|
|
45
52
|
tokens: { id_token: id_token }
|
|
46
53
|
)
|
|
47
54
|
elsif code.present?
|
|
48
|
-
exchange_code_for_user_info(code: code, redirect_uri: redirect_uri, client_id: client_id)
|
|
55
|
+
exchange_code_for_user_info(code: code, redirect_uri: redirect_uri, client_id: client_id, nonce: nonce)
|
|
49
56
|
elsif access_token.present?
|
|
50
57
|
raise StandardId::InvalidRequestError, "Access token login flow is not supported for Apple"
|
|
51
58
|
else
|
|
@@ -82,7 +89,7 @@ module StandardId
|
|
|
82
89
|
params.merge(client_id: client_id)
|
|
83
90
|
end
|
|
84
91
|
|
|
85
|
-
def exchange_code_for_user_info(code:, redirect_uri:, client_id: StandardId.config.apple_client_id)
|
|
92
|
+
def exchange_code_for_user_info(code:, redirect_uri:, client_id: StandardId.config.apple_client_id, nonce: nil)
|
|
86
93
|
ensure_full_credentials!(client_id: client_id)
|
|
87
94
|
raise StandardId::InvalidRequestError, "Missing authorization code" if code.blank?
|
|
88
95
|
|
|
@@ -108,7 +115,7 @@ module StandardId
|
|
|
108
115
|
raise StandardId::InvalidRequestError, "Apple response missing id_token" if id_token.blank?
|
|
109
116
|
|
|
110
117
|
tokens = extract_token_payload(parsed_token)
|
|
111
|
-
user_info = verify_id_token(id_token: id_token, client_id: client_id)
|
|
118
|
+
user_info = verify_id_token(id_token: id_token, client_id: client_id, nonce: nonce)
|
|
112
119
|
|
|
113
120
|
build_response(user_info, tokens: tokens)
|
|
114
121
|
rescue StandardError => e
|
|
@@ -117,7 +124,7 @@ module StandardId
|
|
|
117
124
|
raise StandardId::OAuthError, e.message, cause: e
|
|
118
125
|
end
|
|
119
126
|
|
|
120
|
-
def verify_id_token(id_token:, client_id: StandardId.config.apple_client_id)
|
|
127
|
+
def verify_id_token(id_token:, client_id: StandardId.config.apple_client_id, nonce: nil)
|
|
121
128
|
raise StandardId::InvalidRequestError, "Missing id_token" if id_token.blank?
|
|
122
129
|
raise StandardId::InvalidRequestError, "Apple client_id is not configured" if client_id.blank?
|
|
123
130
|
|
|
@@ -137,6 +144,15 @@ module StandardId
|
|
|
137
144
|
verify_aud: true
|
|
138
145
|
)
|
|
139
146
|
|
|
147
|
+
# Validate nonce if provided (web flow with server-generated nonce)
|
|
148
|
+
if nonce.present?
|
|
149
|
+
token_nonce = verified_payload["nonce"]
|
|
150
|
+
if token_nonce != nonce
|
|
151
|
+
raise StandardId::InvalidRequestError,
|
|
152
|
+
"ID token nonce mismatch. Expected: #{nonce}, got: #{token_nonce}"
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
140
156
|
{
|
|
141
157
|
"sub" => verified_payload["sub"],
|
|
142
158
|
"email" => verified_payload["email"],
|
|
@@ -224,5 +240,3 @@ module StandardId
|
|
|
224
240
|
end
|
|
225
241
|
end
|
|
226
242
|
end
|
|
227
|
-
|
|
228
|
-
StandardId::ProviderRegistry.register(:apple, StandardId::Providers::Apple)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module StandardId
|
|
4
|
+
module Apple
|
|
5
|
+
class Railtie < ::Rails::Railtie
|
|
6
|
+
config.after_initialize do
|
|
7
|
+
StandardId::ProviderRegistry.register(:apple, StandardId::Providers::Apple)
|
|
8
|
+
|
|
9
|
+
Rails.logger.debug("[StandardId::Apple] registered provider") if Rails.logger
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
data/lib/standard_id/apple.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: standard_id-apple
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jaryl Sim
|
|
@@ -69,12 +69,14 @@ files:
|
|
|
69
69
|
- ".rubocop.yml"
|
|
70
70
|
- ".ruby-version"
|
|
71
71
|
- CHANGELOG.md
|
|
72
|
+
- CLAUDE.md
|
|
72
73
|
- CODE_OF_CONDUCT.md
|
|
73
74
|
- LICENSE.txt
|
|
74
75
|
- README.md
|
|
75
76
|
- Rakefile
|
|
76
77
|
- lib/standard_id/apple.rb
|
|
77
78
|
- lib/standard_id/apple/providers/apple.rb
|
|
79
|
+
- lib/standard_id/apple/railtie.rb
|
|
78
80
|
- lib/standard_id/apple/version.rb
|
|
79
81
|
homepage: https://github.com/rarebit-one/standard_id_apple
|
|
80
82
|
licenses:
|
|
@@ -83,6 +85,7 @@ metadata:
|
|
|
83
85
|
homepage_uri: https://github.com/rarebit-one/standard_id_apple
|
|
84
86
|
source_code_uri: https://github.com/rarebit-one/standard_id_apple
|
|
85
87
|
changelog_uri: https://github.com/rarebit-one/standard_id_apple/blob/main/CHANGELOG.md
|
|
88
|
+
bug_tracker_uri: https://github.com/rarebit-one/standard_id_apple/issues
|
|
86
89
|
rdoc_options: []
|
|
87
90
|
require_paths:
|
|
88
91
|
- lib
|
|
@@ -97,7 +100,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
97
100
|
- !ruby/object:Gem::Version
|
|
98
101
|
version: '0'
|
|
99
102
|
requirements: []
|
|
100
|
-
rubygems_version:
|
|
103
|
+
rubygems_version: 4.0.3
|
|
101
104
|
specification_version: 4
|
|
102
105
|
summary: Apple Sign In provider plugin for the StandardId engine.
|
|
103
106
|
test_files: []
|