b-discourse-omniauth-jwt 0.0.4
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/.gitignore +17 -0
- data/.rspec +2 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/Guardfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +85 -0
- data/Rakefile +6 -0
- data/a-discourse-omniauth-jwt.gemspec +30 -0
- data/lib/omniauth/jwt/version.rb +5 -0
- data/lib/omniauth/jwt.rb +2 -0
- data/lib/omniauth/strategies/jwt.rb +57 -0
- data/spec/lib/omniauth/strategies/jwt_spec.rb +65 -0
- data/spec/spec_helper.rb +24 -0
- metadata +173 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 03fa4f03e7a63c3a446f8a34c3d3edc7ed0ef5f17cb2253d8a7e241e44b94273
|
4
|
+
data.tar.gz: 226cc4a1e6a1139038087c7aab2afadd67350c34c64754e416797cb18f60f9ed
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: db4f9eb22aad36323f414f276905a4ec91e3e107122d27a5f0122c21640abca9bb2523ad91cd30be573f14a8311eebb2bf0fc8912b71bc379a77154a4217c5f0
|
7
|
+
data.tar.gz: a8f2599907ce13e382a56f12701293feb68708fa91d678937ae594159da090638965066a3a02a4e0ecd0127045a1c570ee389a94167f485a3bb5c6d69be94bd6
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Michael Bleigh
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
# OmniAuth::JWT
|
2
|
+
|
3
|
+
[](https://travis-ci.org/mbleigh/omniauth-jwt)
|
4
|
+
|
5
|
+
[JSON Web Token](http://self-issued.info/docs/draft-ietf-oauth-json-web-token.html) (JWT) is a simple
|
6
|
+
way to send verified information between two parties online. This can be useful as a mechanism for
|
7
|
+
providing Single Sign-On (SSO) to an application by allowing an authentication server to send a validated
|
8
|
+
claim and log the user in. This is how [Zendesk does SSO](https://support.zendesk.com/entries/23675367-Setting-up-single-sign-on-with-JWT-JSON-Web-Token-),
|
9
|
+
for example.
|
10
|
+
|
11
|
+
OmniAuth::JWT provides a clean, simple wrapper on top of JWT so that you can easily implement this kind
|
12
|
+
of SSO either between your own applications or allow third parties to delegate authentication.
|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
Add this line to your application's Gemfile:
|
17
|
+
|
18
|
+
gem 'omniauth-jwt'
|
19
|
+
|
20
|
+
And then execute:
|
21
|
+
|
22
|
+
$ bundle
|
23
|
+
|
24
|
+
Or install it yourself as:
|
25
|
+
|
26
|
+
$ gem install omniauth-jwt
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
You use OmniAuth::JWT just like you do any other OmniAuth strategy:
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
use OmniAuth::JWT, 'SHAREDSECRET', auth_url: 'http://example.com/login'
|
34
|
+
```
|
35
|
+
|
36
|
+
The first parameter is the shared secret that will be used by the external authenticator to verify
|
37
|
+
that. You must also specify the `auth_url` option to tell the strategy where to redirect to log
|
38
|
+
in. Other available options are:
|
39
|
+
|
40
|
+
* **algorithm:** the algorithm to use to decode the JWT token. This is `HS256` by default but can
|
41
|
+
be set to anything supported by [ruby-jwt](https://github.com/progrium/ruby-jwt)
|
42
|
+
* **uid_claim:** this determines which claim will be used to uniquely identify the user. Defaults
|
43
|
+
to `email`
|
44
|
+
* **required_claims:** array of claims that are required to make this a valid authentication call.
|
45
|
+
Defaults to `['name', 'email']`
|
46
|
+
* **info_map:** array mapping claim values to info hash values. Defaults to mapping `name` and `email`
|
47
|
+
to the same in the info hash.
|
48
|
+
* **valid_within:** integer of how many seconds of time skew you will allow. Defaults to `nil`. If this
|
49
|
+
is set, the `iat` claim becomes required and must be within the specified number of seconds of the
|
50
|
+
current time. This helps to prevent replay attacks.
|
51
|
+
|
52
|
+
### Authentication Process
|
53
|
+
|
54
|
+
When you authenticate through `omniauth-jwt` you can send users to `/auth/jwt` and it will redirect
|
55
|
+
them to the URL specified in the `auth_url` option. From there, the provider must generate a JWT
|
56
|
+
and send it to the `/auth/jwt/callback` URL as a "jwt" parameter:
|
57
|
+
|
58
|
+
/auth/jwt/callback?jwt=ENCODEDJWTGOESHERE
|
59
|
+
|
60
|
+
An example of how to do that in Sinatra:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
require 'jwt'
|
64
|
+
|
65
|
+
get '/login/sso/other-app' do
|
66
|
+
# assuming the user is already logged in and this is available as current_user
|
67
|
+
claims = {
|
68
|
+
id: current_user.id,
|
69
|
+
name: current_user.name,
|
70
|
+
email: current_user.email,
|
71
|
+
iat: Time.now.to_i
|
72
|
+
}
|
73
|
+
|
74
|
+
payload = JWT.encode(claims, ENV['SSO_SECRET'])
|
75
|
+
redirect "http://other-app.com/auth/jwt/callback?jwt=#{payload}"
|
76
|
+
end
|
77
|
+
```
|
78
|
+
|
79
|
+
## Contributing
|
80
|
+
|
81
|
+
1. Fork it
|
82
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
83
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
84
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
85
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'omniauth/jwt/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "b-discourse-omniauth-jwt"
|
8
|
+
spec.version = Omniauth::JWT::VERSION
|
9
|
+
spec.authors = ["Michael Bleigh", "Robin Ward"]
|
10
|
+
spec.email = ["mbleigh@mbleigh.com", "robin.ward@gmail.com"]
|
11
|
+
spec.description = %q{An OmniAuth strategy to accept JWT-based single sign-on.}
|
12
|
+
spec.summary = %q{An OmniAuth strategy to accept JWT-based single sign-on.}
|
13
|
+
spec.homepage = "http://github.com/discourse/discourse-omniauth-jwt"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
spec.add_development_dependency "guard"
|
25
|
+
spec.add_development_dependency "guard-rspec"
|
26
|
+
spec.add_development_dependency "rack-test"
|
27
|
+
|
28
|
+
spec.add_dependency "jwt", "~> 2.8.1"
|
29
|
+
spec.add_dependency "omniauth", "~> 1.1"
|
30
|
+
end
|
data/lib/omniauth/jwt.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'omniauth'
|
2
|
+
require 'jwt'
|
3
|
+
|
4
|
+
module OmniAuth
|
5
|
+
module Strategies
|
6
|
+
class JWT
|
7
|
+
class ClaimInvalid < StandardError; end
|
8
|
+
|
9
|
+
include OmniAuth::Strategy
|
10
|
+
|
11
|
+
args [:secret]
|
12
|
+
|
13
|
+
option :secret, nil
|
14
|
+
option :algorithm, 'HS256'
|
15
|
+
option :uid_claim, 'email'
|
16
|
+
option :required_claims, %w(name email)
|
17
|
+
option :info_map, {"name" => "name", "email" => "email"}
|
18
|
+
option :auth_url, nil
|
19
|
+
option :valid_within, nil
|
20
|
+
|
21
|
+
def request_phase
|
22
|
+
redirect options.auth_url
|
23
|
+
end
|
24
|
+
|
25
|
+
def decoded
|
26
|
+
@decoded ||= ::JWT.decode(request.params['jwt'], options.secret, true, { algorithm: options.algorithm })[0]
|
27
|
+
(options.required_claims || []).each do |field|
|
28
|
+
raise ClaimInvalid.new("Missing required '#{field}' claim.") if !@decoded.key?(field.to_s)
|
29
|
+
end
|
30
|
+
raise ClaimInvalid.new("Missing required 'iat' claim.") if options.valid_within && !@decoded["iat"]
|
31
|
+
raise ClaimInvalid.new("'iat' timestamp claim is too skewed from present.") if options.valid_within && (Time.now.to_i - @decoded["iat"]).abs > options.valid_within
|
32
|
+
@decoded
|
33
|
+
end
|
34
|
+
|
35
|
+
def callback_phase
|
36
|
+
super
|
37
|
+
rescue ClaimInvalid => e
|
38
|
+
fail! :claim_invalid, e
|
39
|
+
end
|
40
|
+
|
41
|
+
uid{ decoded[options.uid_claim] }
|
42
|
+
|
43
|
+
extra do
|
44
|
+
{:raw_info => decoded}
|
45
|
+
end
|
46
|
+
|
47
|
+
info do
|
48
|
+
options.info_map.inject({}) do |h,(k,v)|
|
49
|
+
h[k.to_s] = decoded[v.to_s]
|
50
|
+
h
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class Jwt < JWT; end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe OmniAuth::Strategies::JWT do
|
4
|
+
let(:response_json){ MultiJson.load(last_response.body) }
|
5
|
+
let(:args){ ['imasecret', {auth_url: 'http://example.com/login'}] }
|
6
|
+
|
7
|
+
let(:app){
|
8
|
+
the_args = args
|
9
|
+
Rack::Builder.new do |b|
|
10
|
+
b.use Rack::Session::Cookie, secret: 'sekrit'
|
11
|
+
b.use OmniAuth::Strategies::JWT, *the_args
|
12
|
+
b.run lambda{|env| [200, {}, [(env['omniauth.auth'] || {}).to_json]]}
|
13
|
+
end
|
14
|
+
}
|
15
|
+
|
16
|
+
context 'request phase' do
|
17
|
+
it 'should redirect to the configured login url' do
|
18
|
+
get '/auth/jwt'
|
19
|
+
expect(last_response.status).to eq(302)
|
20
|
+
expect(last_response.headers['Location']).to eq('http://example.com/login')
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'callback phase' do
|
25
|
+
it 'should decode the response' do
|
26
|
+
encoded = JWT.encode({name: 'Bob', email: 'steve@example.com'}, 'imasecret')
|
27
|
+
get '/auth/jwt/callback?jwt=' + encoded
|
28
|
+
expect(response_json["info"]["email"]).to eq("steve@example.com")
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should not work without required fields' do
|
32
|
+
encoded = JWT.encode({name: 'Steve'}, 'imasecret')
|
33
|
+
get '/auth/jwt/callback?jwt=' + encoded
|
34
|
+
expect(last_response.status).to eq(302)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should assign the uid' do
|
38
|
+
encoded = JWT.encode({name: 'Steve', email: 'dude@awesome.com'}, 'imasecret')
|
39
|
+
get '/auth/jwt/callback?jwt=' + encoded
|
40
|
+
expect(response_json["uid"]).to eq('dude@awesome.com')
|
41
|
+
end
|
42
|
+
|
43
|
+
context 'with a :valid_within option set' do
|
44
|
+
let(:args){ ['imasecret', {auth_url: 'http://example.com/login', valid_within: 300}] }
|
45
|
+
|
46
|
+
it 'should work if the iat key is within the time window' do
|
47
|
+
encoded = JWT.encode({name: 'Ted', email: 'ted@example.com', iat: Time.now.to_i}, 'imasecret')
|
48
|
+
get '/auth/jwt/callback?jwt=' + encoded
|
49
|
+
expect(last_response.status).to eq(200)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should not work if the iat key is outside the time window' do
|
53
|
+
encoded = JWT.encode({name: 'Ted', email: 'ted@example.com', iat: Time.now.to_i + 500}, 'imasecret')
|
54
|
+
get '/auth/jwt/callback?jwt=' + encoded
|
55
|
+
expect(last_response.status).to eq(302)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should not work if the iat key is missing' do
|
59
|
+
encoded = JWT.encode({name: 'Ted', email: 'ted@example.com'}, 'imasecret')
|
60
|
+
get '/auth/jwt/callback?jwt=' + encoded
|
61
|
+
expect(last_response.status).to eq(302)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__) + "/../lib"
|
2
|
+
require 'rack/test'
|
3
|
+
|
4
|
+
require 'omniauth/jwt'
|
5
|
+
OmniAuth.config.logger = Logger.new('/dev/null')
|
6
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
7
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
8
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
9
|
+
# loaded once.
|
10
|
+
#
|
11
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
12
|
+
RSpec.configure do |config|
|
13
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
14
|
+
config.run_all_when_everything_filtered = true
|
15
|
+
config.filter_run :focus
|
16
|
+
|
17
|
+
include Rack::Test::Methods
|
18
|
+
|
19
|
+
# Run specs in random order to surface order dependencies. If you find an
|
20
|
+
# order dependency and want to debug it, you can fix the order by providing
|
21
|
+
# the seed, which is printed after each run.
|
22
|
+
# --seed 1234
|
23
|
+
config.order = 'random'
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,173 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: b-discourse-omniauth-jwt
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Michael Bleigh
|
8
|
+
- Robin Ward
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2024-06-15 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bundler
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - "~>"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '1.3'
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - "~>"
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '1.3'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: rake
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: rspec
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: guard
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: guard-rspec
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: rack-test
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
type: :development
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: jwt
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - "~>"
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: 2.8.1
|
105
|
+
type: :runtime
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - "~>"
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: 2.8.1
|
112
|
+
- !ruby/object:Gem::Dependency
|
113
|
+
name: omniauth
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - "~>"
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '1.1'
|
119
|
+
type: :runtime
|
120
|
+
prerelease: false
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - "~>"
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '1.1'
|
126
|
+
description: An OmniAuth strategy to accept JWT-based single sign-on.
|
127
|
+
email:
|
128
|
+
- mbleigh@mbleigh.com
|
129
|
+
- robin.ward@gmail.com
|
130
|
+
executables: []
|
131
|
+
extensions: []
|
132
|
+
extra_rdoc_files: []
|
133
|
+
files:
|
134
|
+
- ".gitignore"
|
135
|
+
- ".rspec"
|
136
|
+
- ".travis.yml"
|
137
|
+
- Gemfile
|
138
|
+
- Guardfile
|
139
|
+
- LICENSE.txt
|
140
|
+
- README.md
|
141
|
+
- Rakefile
|
142
|
+
- a-discourse-omniauth-jwt.gemspec
|
143
|
+
- lib/omniauth/jwt.rb
|
144
|
+
- lib/omniauth/jwt/version.rb
|
145
|
+
- lib/omniauth/strategies/jwt.rb
|
146
|
+
- spec/lib/omniauth/strategies/jwt_spec.rb
|
147
|
+
- spec/spec_helper.rb
|
148
|
+
homepage: http://github.com/discourse/discourse-omniauth-jwt
|
149
|
+
licenses:
|
150
|
+
- MIT
|
151
|
+
metadata: {}
|
152
|
+
post_install_message:
|
153
|
+
rdoc_options: []
|
154
|
+
require_paths:
|
155
|
+
- lib
|
156
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
157
|
+
requirements:
|
158
|
+
- - ">="
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '0'
|
161
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
162
|
+
requirements:
|
163
|
+
- - ">="
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0'
|
166
|
+
requirements: []
|
167
|
+
rubygems_version: 3.0.3.1
|
168
|
+
signing_key:
|
169
|
+
specification_version: 4
|
170
|
+
summary: An OmniAuth strategy to accept JWT-based single sign-on.
|
171
|
+
test_files:
|
172
|
+
- spec/lib/omniauth/strategies/jwt_spec.rb
|
173
|
+
- spec/spec_helper.rb
|