omniauth-honin 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/LICENSE +21 -0
- data/README.md +120 -0
- data/lib/omniauth/honin/version.rb +7 -0
- data/lib/omniauth/strategies/honin.rb +192 -0
- data/lib/omniauth-honin.rb +4 -0
- metadata +175 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 8ba9cb60419c162b8451a3fcb5b2071ac8d5229638d98422b93dbfa9f02e4666
|
|
4
|
+
data.tar.gz: 43893c67e00b951e240e352c2d08f287d2dcadcb85820d00301c9e6cb7c0a479
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: e3aead620f5c9a95604c2714811558d783fadc3940ac29c63f6e8c441c67e414977c7174a9db5686edb9ed7743ee67dc6d5809b4e57874c99bf83d8233ba102a
|
|
7
|
+
data.tar.gz: 0a5bdaa70720965c09c80ba533ce5ea47fa18d11c55fd9fcc2f4279f59b29c1add213dd19aeaf8404f62fe093d82fbdcf3d1e8d41398b8b824e1659eb842e5fa
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Axel Gustav
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# omniauth-honin
|
|
2
|
+
|
|
3
|
+
An OmniAuth strategy for authenticating users via [Honin](https://honin.id) — the privacy-first identity provider.
|
|
4
|
+
|
|
5
|
+
Works with Honin Cloud (`honin.id`), self-hosted Honin instances, and Rails apps that mount the `honin-engine` in IDP mode.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
gem "omniauth-honin"
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Configuration
|
|
14
|
+
|
|
15
|
+
### Honin Cloud
|
|
16
|
+
|
|
17
|
+
```ruby
|
|
18
|
+
# config/initializers/omniauth.rb
|
|
19
|
+
Rails.application.config.middleware.use OmniAuth::Builder do
|
|
20
|
+
provider :honin,
|
|
21
|
+
ENV["HONIN_CLIENT_ID"],
|
|
22
|
+
ENV["HONIN_CLIENT_SECRET"],
|
|
23
|
+
jwks_uri: "https://honin.id/.well-known/jwks.json"
|
|
24
|
+
end
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
`jwks_uri` is optional but recommended for production — it verifies the JWT signature on every login. Without it the access token is decoded without signature verification.
|
|
28
|
+
|
|
29
|
+
### Self-hosted instance (root-mounted)
|
|
30
|
+
|
|
31
|
+
Point `client_options: { site: }` at your server. Everything else is the same.
|
|
32
|
+
|
|
33
|
+
```ruby
|
|
34
|
+
provider :honin,
|
|
35
|
+
ENV["HONIN_CLIENT_ID"],
|
|
36
|
+
ENV["HONIN_CLIENT_SECRET"],
|
|
37
|
+
client_options: { site: "https://auth.acme.co" },
|
|
38
|
+
jwks_uri: "https://auth.acme.co/.well-known/jwks.json"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Self-hosted instance (sub-path mount)
|
|
42
|
+
|
|
43
|
+
If the Honin engine is mounted under a path — e.g. `mount HoninEngine, at: "/auth"` — set `base_path` to that path. The strategy uses it to construct the OAuth endpoints and to verify the `iss` claim in the JWT.
|
|
44
|
+
|
|
45
|
+
```ruby
|
|
46
|
+
provider :honin,
|
|
47
|
+
ENV["HONIN_CLIENT_ID"],
|
|
48
|
+
ENV["HONIN_CLIENT_SECRET"],
|
|
49
|
+
client_options: { site: "https://id.acme.co" },
|
|
50
|
+
base_path: "/auth",
|
|
51
|
+
jwks_uri: "https://id.acme.co/auth/.well-known/jwks.json"
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`base_path` is not needed for Honin Cloud or any instance where the engine is at the root.
|
|
55
|
+
|
|
56
|
+
### Requesting additional scopes
|
|
57
|
+
|
|
58
|
+
Honin supports `email`, `profile`, `timezone`, and `locale`. Scopes must be registered on your Honin Application. The default is `"email profile"`.
|
|
59
|
+
|
|
60
|
+
```ruby
|
|
61
|
+
provider :honin,
|
|
62
|
+
ENV["HONIN_CLIENT_ID"],
|
|
63
|
+
ENV["HONIN_CLIENT_SECRET"],
|
|
64
|
+
scope: "email profile timezone locale"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Auth hash
|
|
68
|
+
|
|
69
|
+
After successful authentication, `request.env["omniauth.auth"]` contains:
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"provider": "honin",
|
|
74
|
+
"uid": "abc123xyz456def789",
|
|
75
|
+
"info": {
|
|
76
|
+
"account_type": "standard",
|
|
77
|
+
"name": "Jane Doe",
|
|
78
|
+
"email": "jane@example.com",
|
|
79
|
+
"email_verified": true,
|
|
80
|
+
"timezone": "America/Toronto",
|
|
81
|
+
"locale": "en"
|
|
82
|
+
},
|
|
83
|
+
"credentials": {
|
|
84
|
+
"token": "eyJhbGciOiJSUzI1NiIs...",
|
|
85
|
+
"token_type": "Bearer",
|
|
86
|
+
"expires": true,
|
|
87
|
+
"expires_at": 1700000000
|
|
88
|
+
},
|
|
89
|
+
"extra": {
|
|
90
|
+
"raw_info": { "...JWT claims..." },
|
|
91
|
+
"granted_scopes": ["email", "profile"],
|
|
92
|
+
"required_scopes": ["email"]
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
`account_type` is `"anonymous"` for anonymous users; scope-dependent fields (`name`, `email`, etc.) are absent.
|
|
98
|
+
|
|
99
|
+
`granted_scopes` reflects what the user actually granted. `required_scopes` are scopes the Honin Application marked as non-deniable.
|
|
100
|
+
|
|
101
|
+
## How it works
|
|
102
|
+
|
|
103
|
+
1. Strategy generates a PKCE code verifier/challenge pair (S256).
|
|
104
|
+
2. User is redirected to the Honin authorize endpoint.
|
|
105
|
+
3. User authenticates and grants consent.
|
|
106
|
+
4. Honin redirects back with an authorization code.
|
|
107
|
+
5. Strategy exchanges the code (with PKCE verifier) for a signed JWT access token.
|
|
108
|
+
6. Strategy decodes the JWT to extract user claims — no separate userinfo request needed.
|
|
109
|
+
|
|
110
|
+
## Development
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
bundle install
|
|
114
|
+
bundle exec rake test
|
|
115
|
+
bundle exec standardrb
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## License
|
|
119
|
+
|
|
120
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "omniauth"
|
|
4
|
+
require "omniauth-oauth2"
|
|
5
|
+
require "jwt"
|
|
6
|
+
require "securerandom"
|
|
7
|
+
require "base64"
|
|
8
|
+
require "digest"
|
|
9
|
+
require "net/http"
|
|
10
|
+
require "uri"
|
|
11
|
+
require "json"
|
|
12
|
+
|
|
13
|
+
module OmniAuth
|
|
14
|
+
module Strategies
|
|
15
|
+
class Honin < OmniAuth::Strategies::OAuth2
|
|
16
|
+
option :name, "honin"
|
|
17
|
+
|
|
18
|
+
option :client_options,
|
|
19
|
+
site: "https://honin.id",
|
|
20
|
+
authorize_url: "/oauth/authorize",
|
|
21
|
+
token_url: "/oauth/token"
|
|
22
|
+
|
|
23
|
+
# Disabled so we own the full PKCE flow; omniauth-oauth2's built-in
|
|
24
|
+
# implementation would conflict with our session keys and S256 enforcement.
|
|
25
|
+
option :pkce, false
|
|
26
|
+
|
|
27
|
+
option :scope, "email profile"
|
|
28
|
+
|
|
29
|
+
# Honin only supports client_secret_post, not client_secret_basic.
|
|
30
|
+
option :auth_token_params, {client_secret_param: "client_secret"}
|
|
31
|
+
|
|
32
|
+
# Sub-path mount support. Set to the engine's mount path when the Honin
|
|
33
|
+
# instance is not at the root — e.g. "/auth" for id.acme.co/auth/...
|
|
34
|
+
# The issuer claim in the JWT is verified against site + base_path.
|
|
35
|
+
# Leave empty (default) for honin.id and root-mounted instances.
|
|
36
|
+
option :base_path, ""
|
|
37
|
+
|
|
38
|
+
option :jwks_uri, nil
|
|
39
|
+
option :jwks, nil
|
|
40
|
+
|
|
41
|
+
PKCE_VERIFIER_LENGTH = 64
|
|
42
|
+
|
|
43
|
+
def request_phase
|
|
44
|
+
generate_pkce!
|
|
45
|
+
super
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def authorize_params
|
|
49
|
+
super.tap do |params|
|
|
50
|
+
params[:code_challenge] = session[:honin_pkce_challenge]
|
|
51
|
+
params[:code_challenge_method] = "S256"
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def token_params
|
|
56
|
+
super.tap do |params|
|
|
57
|
+
params[:code_verifier] = session[:honin_pkce_verifier]
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def callback_phase
|
|
62
|
+
super
|
|
63
|
+
ensure
|
|
64
|
+
clear_pkce_session!
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
uid { decoded_jwt["sub"] }
|
|
68
|
+
|
|
69
|
+
info do
|
|
70
|
+
jwt = decoded_jwt
|
|
71
|
+
{
|
|
72
|
+
account_type: jwt["account_type"],
|
|
73
|
+
name: jwt["display_name"],
|
|
74
|
+
email: jwt["email"],
|
|
75
|
+
email_verified: jwt["email_verified"],
|
|
76
|
+
timezone: jwt["timezone"],
|
|
77
|
+
locale: jwt["locale"]
|
|
78
|
+
}.compact
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
extra do
|
|
82
|
+
jwt = decoded_jwt
|
|
83
|
+
{
|
|
84
|
+
raw_info: raw_info,
|
|
85
|
+
granted_scopes: jwt["granted_scopes"],
|
|
86
|
+
required_scopes: jwt["required_scopes"]
|
|
87
|
+
}.compact
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def client
|
|
91
|
+
@client ||= ::OAuth2::Client.new(options.client_id, options.client_secret,
|
|
92
|
+
site: options.client_options.site,
|
|
93
|
+
authorize_url: "#{options.base_path}/oauth/authorize",
|
|
94
|
+
token_url: "#{options.base_path}/oauth/token")
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def raw_info
|
|
98
|
+
@raw_info ||= decoded_jwt
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def decoded_jwt
|
|
102
|
+
@decoded_jwt ||= begin
|
|
103
|
+
token = access_token.token
|
|
104
|
+
|
|
105
|
+
if jwks_verification_available?
|
|
106
|
+
decode_verified_jwt(token)
|
|
107
|
+
else
|
|
108
|
+
decode_unverified_jwt(token)
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
private
|
|
114
|
+
|
|
115
|
+
def generate_pkce!
|
|
116
|
+
verifier = SecureRandom.urlsafe_base64(PKCE_VERIFIER_LENGTH)
|
|
117
|
+
challenge = Base64.urlsafe_encode64(
|
|
118
|
+
Digest::SHA256.digest(verifier),
|
|
119
|
+
padding: false
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
session[:honin_pkce_verifier] = verifier
|
|
123
|
+
session[:honin_pkce_challenge] = challenge
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def clear_pkce_session!
|
|
127
|
+
session.delete(:honin_pkce_verifier)
|
|
128
|
+
session.delete(:honin_pkce_challenge)
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def jwks_verification_available?
|
|
132
|
+
(options.jwks_uri && !options.jwks_uri.to_s.empty?) ||
|
|
133
|
+
(!options.jwks.nil? && options.jwks != false)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def decode_verified_jwt(token)
|
|
137
|
+
decode_opts = {
|
|
138
|
+
algorithms: ["RS256"],
|
|
139
|
+
verify_iss: true,
|
|
140
|
+
iss: "#{options.client_options.site}#{options.base_path}",
|
|
141
|
+
verify_aud: true,
|
|
142
|
+
aud: options.client_id
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
payload, = JWT.decode(token, nil, true, decode_opts.merge(jwks: resolve_jwk_set))
|
|
146
|
+
payload
|
|
147
|
+
rescue JWT::DecodeError, JWT::VerificationError, JWT::ExpiredSignature,
|
|
148
|
+
JWT::InvalidIssuerError, JWT::JWKError => e
|
|
149
|
+
raise OmniAuth::Strategies::OAuth2::CallbackError.new(:jwt_verification_failed, e.message)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def decode_unverified_jwt(token)
|
|
153
|
+
payload, = JWT.decode(token, nil, false)
|
|
154
|
+
payload
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def resolve_jwk_set
|
|
158
|
+
if options.jwks_uri && !options.jwks_uri.to_s.empty?
|
|
159
|
+
fetch_jwks(options.jwks_uri)
|
|
160
|
+
else
|
|
161
|
+
coerce_jwks(options.jwks)
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def coerce_jwks(jwks)
|
|
166
|
+
case jwks
|
|
167
|
+
when JWT::JWK::Set
|
|
168
|
+
jwks
|
|
169
|
+
when Hash
|
|
170
|
+
JWT::JWK::Set.new(jwks[:keys] || jwks["keys"] || [jwks])
|
|
171
|
+
when Array
|
|
172
|
+
JWT::JWK::Set.new(jwks)
|
|
173
|
+
else
|
|
174
|
+
raise ArgumentError, "jwks must be a Hash, Array, or JWT::JWK::Set, got #{jwks.class}"
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def fetch_jwks(uri)
|
|
179
|
+
response = Net::HTTP.get_response(URI.parse(uri))
|
|
180
|
+
unless response.is_a?(Net::HTTPSuccess)
|
|
181
|
+
raise OmniAuth::Strategies::OAuth2::CallbackError.new(
|
|
182
|
+
:jwks_fetch_failed, "HTTP #{response.code}"
|
|
183
|
+
)
|
|
184
|
+
end
|
|
185
|
+
body = JSON.parse(response.body)
|
|
186
|
+
JWT::JWK::Set.new(body["keys"] || [body])
|
|
187
|
+
rescue JSON::ParserError, JWT::JWKError => e
|
|
188
|
+
raise OmniAuth::Strategies::OAuth2::CallbackError.new(:jwks_fetch_failed, e.message)
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: omniauth-honin
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Axel Gustav
|
|
8
|
+
bindir: exe
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 2026-04-21 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: omniauth
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - "~>"
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '2.0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '2.0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: omniauth-oauth2
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '1.8'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '1.8'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: jwt
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '2.7'
|
|
47
|
+
type: :runtime
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '2.7'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: rake
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '13.0'
|
|
61
|
+
type: :development
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '13.0'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: minitest
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - "~>"
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '5.22'
|
|
75
|
+
type: :development
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - "~>"
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '5.22'
|
|
82
|
+
- !ruby/object:Gem::Dependency
|
|
83
|
+
name: minitest-reporters
|
|
84
|
+
requirement: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - "~>"
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '1.6'
|
|
89
|
+
type: :development
|
|
90
|
+
prerelease: false
|
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - "~>"
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: '1.6'
|
|
96
|
+
- !ruby/object:Gem::Dependency
|
|
97
|
+
name: standard
|
|
98
|
+
requirement: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - "~>"
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '1.35'
|
|
103
|
+
type: :development
|
|
104
|
+
prerelease: false
|
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - "~>"
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '1.35'
|
|
110
|
+
- !ruby/object:Gem::Dependency
|
|
111
|
+
name: rack-test
|
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
|
113
|
+
requirements:
|
|
114
|
+
- - "~>"
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
version: '2.1'
|
|
117
|
+
type: :development
|
|
118
|
+
prerelease: false
|
|
119
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
120
|
+
requirements:
|
|
121
|
+
- - "~>"
|
|
122
|
+
- !ruby/object:Gem::Version
|
|
123
|
+
version: '2.1'
|
|
124
|
+
- !ruby/object:Gem::Dependency
|
|
125
|
+
name: webmock
|
|
126
|
+
requirement: !ruby/object:Gem::Requirement
|
|
127
|
+
requirements:
|
|
128
|
+
- - "~>"
|
|
129
|
+
- !ruby/object:Gem::Version
|
|
130
|
+
version: '3.23'
|
|
131
|
+
type: :development
|
|
132
|
+
prerelease: false
|
|
133
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
134
|
+
requirements:
|
|
135
|
+
- - "~>"
|
|
136
|
+
- !ruby/object:Gem::Version
|
|
137
|
+
version: '3.23'
|
|
138
|
+
description: An OmniAuth strategy for authenticating users via the Honin identity
|
|
139
|
+
provider. Supports Honin Cloud (honin.id), self-hosted Honin instances, and apps
|
|
140
|
+
that mount the honin-engine in IDP mode.
|
|
141
|
+
email:
|
|
142
|
+
- dev@axelgustav.de
|
|
143
|
+
executables: []
|
|
144
|
+
extensions: []
|
|
145
|
+
extra_rdoc_files: []
|
|
146
|
+
files:
|
|
147
|
+
- LICENSE
|
|
148
|
+
- README.md
|
|
149
|
+
- lib/omniauth-honin.rb
|
|
150
|
+
- lib/omniauth/honin/version.rb
|
|
151
|
+
- lib/omniauth/strategies/honin.rb
|
|
152
|
+
homepage: https://codefloe.com/GusTech/omniauth-honin
|
|
153
|
+
licenses:
|
|
154
|
+
- MIT
|
|
155
|
+
metadata:
|
|
156
|
+
homepage_uri: https://honin.id/developers
|
|
157
|
+
source_code_uri: https://codefloe.com/GusTech/omniauth-honin
|
|
158
|
+
rdoc_options: []
|
|
159
|
+
require_paths:
|
|
160
|
+
- lib
|
|
161
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
162
|
+
requirements:
|
|
163
|
+
- - ">="
|
|
164
|
+
- !ruby/object:Gem::Version
|
|
165
|
+
version: '3.0'
|
|
166
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
167
|
+
requirements:
|
|
168
|
+
- - ">="
|
|
169
|
+
- !ruby/object:Gem::Version
|
|
170
|
+
version: '0'
|
|
171
|
+
requirements: []
|
|
172
|
+
rubygems_version: 3.6.3
|
|
173
|
+
specification_version: 4
|
|
174
|
+
summary: Honin OAuth2 strategy for OmniAuth
|
|
175
|
+
test_files: []
|