mapkit_token 1.0.0 → 1.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/README.md +65 -9
- data/app/controllers/mapkit_token/mapkit_token_controller.rb +10 -15
- data/lib/mapkit_token/config.rb +138 -0
- data/lib/mapkit_token/engine.rb +2 -0
- data/lib/mapkit_token/version.rb +1 -1
- data/lib/mapkit_token.rb +9 -1
- data/mapkit_token.gemspec +1 -2
- metadata +8 -25
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '0366869d9c259cd6a25c28915b9f71b851b6a283bd881802f6af2b8e7c8a805c'
|
|
4
|
+
data.tar.gz: 29e882698f549c01f296d9d77ba3f96ea4d7905eaeca113fd57e66c2d9a3bb9d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e80969e65ab3322b4d9e2712333f995bd1ec46fef965c89af2bda595e2fb6575c04ffec16f18c2c398066fea59c97d0a7cd361c078dc2136c25b17d145acb828
|
|
7
|
+
data.tar.gz: dc34fe4c6b9210ce2f0a4849cd44e94f246c65c0e054443bc87965f5a6c5b4fce157e9c47ae5bafe1324f4ecd0410e569e75d2331d3443441884fce4c48a5425
|
data/README.md
CHANGED
|
@@ -24,30 +24,86 @@ Before you can use this gem, you need a Maps Identifer (i.e., Maps ID) and priva
|
|
|
24
24
|
|
|
25
25
|
[Creating a Maps Identifier and a Private Key](https://developer.apple.com/documentation/mapkitjs/creating_a_maps_identifier_and_a_private_key)
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
You need three pieces of information: the private key, the MapKit JS Key ID, and your Apple Developer Team ID.
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
- MapKit JS Key ID
|
|
31
|
-
- Apple Developer Team ID
|
|
29
|
+
You can store them in an initializer, in your Rails credentials, or in environment variables. Use whichever fits the machine your application runs on. The gem checks those places in that order for each setting.
|
|
32
30
|
|
|
33
|
-
|
|
31
|
+
The key itself can be given either as the contents of the `.p8` file or as a path to it. The gem looks for the contents in all three places before it looks for a path. This means that if a server sets the key contents in its environment, that value is used even when the credentials point to a file that doesn't exist on that server.
|
|
32
|
+
|
|
33
|
+
### Option 1: Path to the key file in credentials
|
|
34
|
+
|
|
35
|
+
Add the `.p8` file from Apple to your application folder, then edit your credentials:
|
|
34
36
|
|
|
35
37
|
$ EDITOR=vim rails credentials:edit
|
|
36
38
|
|
|
37
|
-
|
|
39
|
+
```yaml
|
|
40
|
+
mapkit:
|
|
41
|
+
auth_key_path: AuthKey_XXXXXXXXXX.p8
|
|
42
|
+
auth_key_id: XXXXXXXXXX
|
|
43
|
+
apple_team_id: XXXXXXXXXX
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
A relative path is resolved from `Rails.root`. An absolute path is used as is. If you have different AuthKey files for different environments, edit each environment's credentials separately:
|
|
38
47
|
|
|
39
48
|
$ EDITOR=vim rails credentials:edit --environment development
|
|
40
49
|
|
|
41
|
-
|
|
50
|
+
The gem provides legacy support for Rails secrets, so if your app uses Rails 4.1 through 5.1, you can store the same information in `/config/secrets.yml` and it will just work.
|
|
51
|
+
|
|
52
|
+
### Option 2: Key contents in credentials
|
|
53
|
+
|
|
54
|
+
If shipping the `.p8` file is inconvenient (for example, in a container image or on a server built only from the repository), you can paste the contents of the file into your credentials instead:
|
|
42
55
|
|
|
43
56
|
```yaml
|
|
44
57
|
mapkit:
|
|
45
|
-
|
|
58
|
+
auth_key: |
|
|
59
|
+
-----BEGIN PRIVATE KEY-----
|
|
60
|
+
MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQg...
|
|
61
|
+
-----END PRIVATE KEY-----
|
|
46
62
|
auth_key_id: XXXXXXXXXX
|
|
47
63
|
apple_team_id: XXXXXXXXXX
|
|
48
64
|
```
|
|
49
65
|
|
|
50
|
-
|
|
66
|
+
### Option 3: Environment variables
|
|
67
|
+
|
|
68
|
+
You can also set everything with environment variables. This works well for deployments that keep secrets outside the repository:
|
|
69
|
+
|
|
70
|
+
```sh
|
|
71
|
+
MAPKIT_AUTH_KEY_ID=XXXXXXXXXX
|
|
72
|
+
MAPKIT_APPLE_TEAM_ID=XXXXXXXXXX
|
|
73
|
+
|
|
74
|
+
# Either the contents of the .p8 file...
|
|
75
|
+
MAPKIT_AUTH_KEY="$(cat AuthKey_XXXXXXXXXX.p8)"
|
|
76
|
+
|
|
77
|
+
# ...or the path to it, if the file is on the machine
|
|
78
|
+
MAPKIT_AUTH_KEY_PATH=/etc/mapkit/AuthKey_XXXXXXXXXX.p8
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The key spans several lines, and some tools can't set an environment variable that contains newlines. For those cases, `MAPKIT_AUTH_KEY` also accepts two single-line formats:
|
|
82
|
+
|
|
83
|
+
- The key with each newline written as `\n`
|
|
84
|
+
- The whole file encoded as base64 (`base64 -w0 AuthKey_XXXXXXXXXX.p8`)
|
|
85
|
+
|
|
86
|
+
### Option 4: An initializer
|
|
87
|
+
|
|
88
|
+
If you'd rather configure the gem in code (for example, to read the key from a secrets manager or from environment variables with your own names), create `config/initializers/mapkit_token.rb`:
|
|
89
|
+
|
|
90
|
+
```ruby
|
|
91
|
+
MapkitToken.setup do |config|
|
|
92
|
+
config.auth_key = Vault.read("mapkit").data[:p8]
|
|
93
|
+
config.auth_key_id = ENV.fetch("MY_MAPKIT_KEY_ID")
|
|
94
|
+
config.apple_team_id = ENV.fetch("MY_APPLE_TEAM_ID")
|
|
95
|
+
end
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
You can also set `config.app_root` here to resolve a relative `auth_key_path` from a folder other than `Rails.root`.
|
|
99
|
+
|
|
100
|
+
### Missing settings
|
|
101
|
+
|
|
102
|
+
If a setting can't be found, the gem raises `MapkitToken::ConfigurationError` with a message that says what's missing and where you can set it. You get this clear error instead of a confusing failure later on from an unreadable key.
|
|
103
|
+
|
|
104
|
+
To check whether a key is configured without raising an error, call `MapkitToken.config.auth_key?`. This is useful if you want to skip rendering a map when no token is available.
|
|
105
|
+
|
|
106
|
+
After reloading your application, it will have a new endpoint `/mapkit_token` that returns JWTs that are valid for 30 minutes. The application's hostname is added to the JWT payload to specify that the tokens only can used by the application itself.
|
|
51
107
|
|
|
52
108
|
Use the endpoint for the `authorizationCallback` function that MapKit JS calls whenever it detects that a new token is needed.
|
|
53
109
|
|
|
@@ -1,28 +1,23 @@
|
|
|
1
1
|
module MapkitToken
|
|
2
2
|
class MapkitTokenController < ApplicationController
|
|
3
3
|
|
|
4
|
-
def
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
def show
|
|
5
|
+
render plain: Mapkit.token.generate(
|
|
6
|
+
auth_key: mapkit.auth_key,
|
|
7
|
+
auth_key_id: mapkit.auth_key_id,
|
|
8
|
+
apple_team_id: mapkit.apple_team_id,
|
|
9
|
+
base_url: base_url
|
|
10
|
+
)
|
|
10
11
|
end
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
mapkit[:auth_key_id]
|
|
14
|
-
end
|
|
13
|
+
private
|
|
15
14
|
|
|
16
|
-
def
|
|
17
|
-
|
|
15
|
+
def mapkit
|
|
16
|
+
MapkitToken.config
|
|
18
17
|
end
|
|
19
18
|
|
|
20
19
|
def base_url
|
|
21
20
|
request.protocol + request.host
|
|
22
21
|
end
|
|
23
|
-
|
|
24
|
-
def show
|
|
25
|
-
render plain: Mapkit.token.generate(auth_key: auth_key, auth_key_id: auth_key_id, apple_team_id: apple_team_id, base_url: base_url)
|
|
26
|
-
end
|
|
27
22
|
end
|
|
28
23
|
end
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
require "pathname"
|
|
2
|
+
|
|
3
|
+
module MapkitToken
|
|
4
|
+
class ConfigurationError < StandardError; end
|
|
5
|
+
|
|
6
|
+
class Config
|
|
7
|
+
ENV_NAMES = {
|
|
8
|
+
:auth_key => "MAPKIT_AUTH_KEY",
|
|
9
|
+
:auth_key_path => "MAPKIT_AUTH_KEY_PATH",
|
|
10
|
+
:auth_key_id => "MAPKIT_AUTH_KEY_ID",
|
|
11
|
+
:apple_team_id => "MAPKIT_APPLE_TEAM_ID"
|
|
12
|
+
}.freeze
|
|
13
|
+
|
|
14
|
+
PEM_MARKER = "-----BEGIN".freeze
|
|
15
|
+
|
|
16
|
+
def auth_key
|
|
17
|
+
carried = setting(:auth_key)
|
|
18
|
+
return pem(carried) if carried.present?
|
|
19
|
+
|
|
20
|
+
path = auth_key_path
|
|
21
|
+
if path.blank?
|
|
22
|
+
raise ConfigurationError, explain("No MapKit auth key. Set the contents " \
|
|
23
|
+
"of the .p8 with #{places(:auth_key)}, or a path to it with " \
|
|
24
|
+
"#{places(:auth_key_path)}.")
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
file = expand_path(path)
|
|
28
|
+
unless File.exist?(file)
|
|
29
|
+
raise ConfigurationError, "MapKit auth key file not found at #{file}"
|
|
30
|
+
end
|
|
31
|
+
pem(File.read(file))
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def auth_key_path
|
|
35
|
+
setting(:auth_key_path)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def auth_key_id
|
|
39
|
+
require_setting(:auth_key_id, "No MapKit key id.")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def apple_team_id
|
|
43
|
+
require_setting(:apple_team_id, "No Apple team id.")
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def auth_key?
|
|
47
|
+
auth_key
|
|
48
|
+
true
|
|
49
|
+
rescue ConfigurationError
|
|
50
|
+
false
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
private
|
|
54
|
+
|
|
55
|
+
def setting(name)
|
|
56
|
+
from_initializer(name) || from_credentials(name) || from_env(name)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def require_setting(name, message)
|
|
60
|
+
value = setting(name)
|
|
61
|
+
if value.blank?
|
|
62
|
+
raise ConfigurationError, explain("#{message} Set it with #{places(name)}.")
|
|
63
|
+
end
|
|
64
|
+
value
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def places(name)
|
|
68
|
+
"config.#{name} in MapkitToken.setup, `mapkit: #{name}` in the " \
|
|
69
|
+
"credentials, or #{ENV_NAMES.fetch(name)}"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# A credentials file that can't be decrypted reads as empty, so the
|
|
73
|
+
# environment still gets its turn; say so when nothing is found there.
|
|
74
|
+
def explain(message)
|
|
75
|
+
return message if @credentials_error.nil?
|
|
76
|
+
"#{message} The credentials could not be read " \
|
|
77
|
+
"(#{@credentials_error.class}), so any MapKit settings in them were skipped."
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def from_initializer(name)
|
|
81
|
+
MapkitToken.public_send(name).presence
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def from_credentials(name)
|
|
85
|
+
credentials[name].presence
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def from_env(name)
|
|
89
|
+
ENV[ENV_NAMES.fetch(name)].presence
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def credentials
|
|
93
|
+
store = credentials_store
|
|
94
|
+
return {} if store.nil?
|
|
95
|
+
store.respond_to?(:to_h) ? store.to_h.symbolize_keys : {}
|
|
96
|
+
rescue StandardError => e
|
|
97
|
+
@credentials_error = e
|
|
98
|
+
{}
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def credentials_store
|
|
102
|
+
app = application
|
|
103
|
+
return nil if app.nil?
|
|
104
|
+
|
|
105
|
+
if app.respond_to?(:credentials)
|
|
106
|
+
app.credentials.mapkit
|
|
107
|
+
elsif app.respond_to?(:secrets)
|
|
108
|
+
app.secrets.mapkit
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def application
|
|
113
|
+
return nil unless defined?(Rails) && Rails.respond_to?(:application)
|
|
114
|
+
Rails.application
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def app_root
|
|
118
|
+
MapkitToken.app_root || (application && Rails.root) || Dir.pwd
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def expand_path(path)
|
|
122
|
+
pathname = Pathname.new(path.to_s)
|
|
123
|
+
pathname.absolute? ? pathname.to_s : File.join(app_root.to_s, pathname.to_s)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def pem(value)
|
|
127
|
+
key = value.to_s.strip.gsub('\n', "\n")
|
|
128
|
+
return terminate(key) if key.include?(PEM_MARKER)
|
|
129
|
+
|
|
130
|
+
decoded = key.unpack1("m").force_encoding(Encoding::UTF_8)
|
|
131
|
+
decoded.include?(PEM_MARKER) ? terminate(decoded) : key
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def terminate(key)
|
|
135
|
+
key.end_with?("\n") ? key : key + "\n"
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
data/lib/mapkit_token/engine.rb
CHANGED
data/lib/mapkit_token/version.rb
CHANGED
data/lib/mapkit_token.rb
CHANGED
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
require "active_support/all"
|
|
2
2
|
require "mapkit_token/version"
|
|
3
|
+
require "mapkit_token/config"
|
|
3
4
|
require "mapkit_token/app/models/mapkit.rb"
|
|
4
5
|
require "jwt"
|
|
5
6
|
|
|
6
7
|
module MapkitToken
|
|
7
8
|
mattr_accessor :app_root
|
|
9
|
+
mattr_accessor :auth_key
|
|
10
|
+
mattr_accessor :auth_key_path
|
|
11
|
+
mattr_accessor :auth_key_id
|
|
12
|
+
mattr_accessor :apple_team_id
|
|
8
13
|
|
|
9
14
|
def self.setup
|
|
10
15
|
yield self
|
|
11
16
|
end
|
|
17
|
+
|
|
18
|
+
def self.config
|
|
19
|
+
Config.new
|
|
20
|
+
end
|
|
12
21
|
end
|
|
13
22
|
|
|
14
23
|
require "mapkit_token/engine"
|
|
15
|
-
|
data/mapkit_token.gemspec
CHANGED
|
@@ -19,8 +19,7 @@ Gem::Specification.new do |spec|
|
|
|
19
19
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
20
20
|
spec.require_paths = ["lib"]
|
|
21
21
|
|
|
22
|
-
spec.add_development_dependency "
|
|
23
|
-
spec.add_development_dependency "rake", "~> 10.0"
|
|
22
|
+
spec.add_development_dependency "rake", ">= 13.0"
|
|
24
23
|
spec.add_development_dependency "rspec", "~> 3.0"
|
|
25
24
|
|
|
26
25
|
spec.add_dependency "activesupport"
|
metadata
CHANGED
|
@@ -1,43 +1,28 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mapkit_token
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Michael Edlund
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: exe
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
|
-
- !ruby/object:Gem::Dependency
|
|
14
|
-
name: bundler
|
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
|
16
|
-
requirements:
|
|
17
|
-
- - "~>"
|
|
18
|
-
- !ruby/object:Gem::Version
|
|
19
|
-
version: '1.16'
|
|
20
|
-
type: :development
|
|
21
|
-
prerelease: false
|
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
-
requirements:
|
|
24
|
-
- - "~>"
|
|
25
|
-
- !ruby/object:Gem::Version
|
|
26
|
-
version: '1.16'
|
|
27
12
|
- !ruby/object:Gem::Dependency
|
|
28
13
|
name: rake
|
|
29
14
|
requirement: !ruby/object:Gem::Requirement
|
|
30
15
|
requirements:
|
|
31
|
-
- - "
|
|
16
|
+
- - ">="
|
|
32
17
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: '
|
|
18
|
+
version: '13.0'
|
|
34
19
|
type: :development
|
|
35
20
|
prerelease: false
|
|
36
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
22
|
requirements:
|
|
38
|
-
- - "
|
|
23
|
+
- - ">="
|
|
39
24
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: '
|
|
25
|
+
version: '13.0'
|
|
41
26
|
- !ruby/object:Gem::Dependency
|
|
42
27
|
name: rspec
|
|
43
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -94,7 +79,6 @@ dependencies:
|
|
|
94
79
|
- - ">="
|
|
95
80
|
- !ruby/object:Gem::Version
|
|
96
81
|
version: '0'
|
|
97
|
-
description:
|
|
98
82
|
email:
|
|
99
83
|
- medlund@mac.com
|
|
100
84
|
executables: []
|
|
@@ -114,13 +98,13 @@ files:
|
|
|
114
98
|
- config/routes.rb
|
|
115
99
|
- lib/mapkit_token.rb
|
|
116
100
|
- lib/mapkit_token/app/models/mapkit.rb
|
|
101
|
+
- lib/mapkit_token/config.rb
|
|
117
102
|
- lib/mapkit_token/engine.rb
|
|
118
103
|
- lib/mapkit_token/version.rb
|
|
119
104
|
- mapkit_token.gemspec
|
|
120
105
|
homepage: https://github.com/arcticleo/mapkit_token
|
|
121
106
|
licenses: []
|
|
122
107
|
metadata: {}
|
|
123
|
-
post_install_message:
|
|
124
108
|
rdoc_options: []
|
|
125
109
|
require_paths:
|
|
126
110
|
- lib
|
|
@@ -135,8 +119,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
135
119
|
- !ruby/object:Gem::Version
|
|
136
120
|
version: '0'
|
|
137
121
|
requirements: []
|
|
138
|
-
rubygems_version:
|
|
139
|
-
signing_key:
|
|
122
|
+
rubygems_version: 4.0.20
|
|
140
123
|
specification_version: 4
|
|
141
124
|
summary: MapKit JS token endpoint provider.
|
|
142
125
|
test_files: []
|