omniauth-authentiq 0.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -2
- data/README.md +11 -34
- data/lib/omniauth/authentiq/version.rb +1 -1
- data/lib/omniauth/strategies/authentiq.rb +46 -16
- data/lib/omniauth/strategies/oidc/back_channel_logout_request.rb +103 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5d7e7b3e51f99cded0ba659c1161ece4f4f0d0c3
|
4
|
+
data.tar.gz: fb5c1e16c513836280b96a756789d79eeb38c4fe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ff537913cec88b237d0820091b988dec465f6c981e4a2c52b3fd93ee49c4f707dd5d39c7c489ae258fa0adbc63f7ea6df0a592efac508821f1c57777d203323f
|
7
|
+
data.tar.gz: a7b172b8ff284d0fd07c085e6fcc59e5adfd85dcbbfdb899d6b681508a16fef0bb1575bd22120e3c08dc3051d50f6d205998064d80c9c5ae7d4a5fee6a02fd65
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
# OmniAuth Authentiq
|
2
2
|
|
3
3
|
Official [OmniAuth](https://github.com/omniauth/omniauth/wiki) strategy for authenticating with an Authentiq ID mobile app ([iOS](https://itunes.apple.com/us/app/authentiq-id/id964932341), [Android](https://play.google.com/store/apps/details?id=com.authentiq.authentiqid)).
|
4
|
-
|
4
|
+
|
5
|
+
Application credentials (YOUR_CLIENT_ID and YOUR_CLIENT_SECRET below) can be obtained [at Authentiq](https://www.authentiq.com/register/?utm_source=github&utm_medium=readme&utm_campaign=omniauth).
|
5
6
|
|
6
7
|
## Installation
|
7
8
|
|
8
9
|
Add this line to your application's Gemfile
|
9
10
|
|
10
11
|
```ruby
|
11
|
-
gem 'omniauth-authentiq', '~> 0.2.
|
12
|
+
gem 'omniauth-authentiq', '~> 0.2.3'
|
12
13
|
```
|
13
14
|
|
14
15
|
Then bundle:
|
@@ -20,41 +21,17 @@ Then bundle:
|
|
20
21
|
```ruby
|
21
22
|
use OmniAuth::Builder do
|
22
23
|
provider :authentiq, ENV['AUTHENTIQ_KEY'], ENV['AUTHENTIQ_SECRET'],
|
23
|
-
scope: 'aq:name email~rs aq:push'
|
24
|
-
|
25
|
-
```
|
26
|
-
|
27
|
-
# Scopes
|
28
|
-
|
29
|
-
Authentiq adds the capability to request personal information like name, email, phone number, and address from the Authentiq ID app ([iOS](https://itunes.apple.com/us/app/authentiq-id/id964932341), [Android](https://play.google.com/store/apps/details?id=com.authentiq.authentiqid)).
|
30
|
-
During authentication, and only after the user consents, this information will be shared by the Authentiq ID app.
|
31
|
-
|
32
|
-
Requesting specific information or "scopes" is done by modifying the `scope` parameter in the basic usage example above.
|
33
|
-
Depending on your implementation, you may also need to provide the `redirect_uri` parameter.
|
34
|
-
|
35
|
-
Example:
|
36
|
-
```ruby
|
37
|
-
use OmniAuth::Builder do
|
38
|
-
provider :authentiq, ENV['AUTHENTIQ_KEY'], ENV['AUTHENTIQ_SECRET'],
|
39
|
-
scope: 'aq:name email~rs aq:push phone address',
|
40
|
-
redirect_uri: '<REDIRECT_URI>'
|
24
|
+
scope: 'aq:name email~rs aq:push',
|
25
|
+
enable_remote_sign_out: false
|
41
26
|
end
|
42
27
|
```
|
43
28
|
|
44
|
-
|
45
|
-
- `aq:name` for Name
|
46
|
-
- `email` for Email
|
47
|
-
- `phone` for Phone
|
48
|
-
- `address` for Address
|
49
|
-
- `aq:location` for Location (geo coordinates)
|
50
|
-
- `aq:push` to request permission to sign in via Push Notifications in the Authentiq ID app
|
51
|
-
|
52
|
-
Append `~r` to a scope to explicitly require it from the user.
|
53
|
-
|
54
|
-
Append `~s` to phone or email scope to explicitly require a verified (signed) scope.
|
55
|
-
|
56
|
-
The `~s` and `~r` can be combined to `~rs` to indicate that the scope is both required and should be / have been verified.
|
29
|
+
You can read the wiki for more extensive infomation on how to use the Authentiq Omniauth strategy for your rails application
|
57
30
|
|
31
|
+
* [Homepage](https://github.com/AuthentiqID/omniauth-authentiq/wiki)
|
32
|
+
* [Installation and basic usage](https://github.com/AuthentiqID/omniauth-authentiq/wiki/Installation-and-basic-usage)
|
33
|
+
* [Scopes, redirect uri configuration and response data](https://github.com/AuthentiqID/omniauth-authentiq/wiki/Scopes,-redirect-URI-configuration-and-responses)
|
34
|
+
* [Remote Logout (Backchannel-logout)](https://github.com/AuthentiqID/omniauth-authentiq/wiki/Remote-logout)
|
58
35
|
|
59
36
|
## Tests
|
60
37
|
|
@@ -62,4 +39,4 @@ Tests are coming soon.
|
|
62
39
|
|
63
40
|
## Contributing
|
64
41
|
|
65
|
-
Bug reports and pull requests are welcome
|
42
|
+
Bug reports and pull requests are welcome [here](https://github.com/AuthentiqID/omniauth-authentiq)
|
@@ -3,29 +3,26 @@ require 'omniauth-oauth2'
|
|
3
3
|
module OmniAuth
|
4
4
|
module Strategies
|
5
5
|
class Authentiq < OmniAuth::Strategies::OAuth2
|
6
|
-
|
6
|
+
autoload :BackChannelLogoutRequest, 'omniauth/strategies/oidc/back_channel_logout_request'
|
7
|
+
|
7
8
|
BASE_URL = 'https://connect.authentiq.io/'
|
8
9
|
|
9
|
-
# Authentiq strategy name
|
10
10
|
option :name, 'authentiq'
|
11
11
|
|
12
|
-
# Build the basic client options (url, authorization url, token url)
|
13
12
|
option :client_options, {
|
14
13
|
:site => BASE_URL,
|
15
14
|
:authorize_url => '/authorize',
|
16
15
|
:token_url => '/token'
|
17
16
|
}
|
18
17
|
|
19
|
-
|
20
|
-
option :authorize_options, [:scope, :display]
|
18
|
+
option :authorize_options, [:scope]
|
21
19
|
|
22
20
|
# These are called after authentication has succeeded. If
|
23
21
|
# possible, you should try to set the UID without making
|
24
|
-
# additional calls (if the user id is returned with the
|
25
|
-
# or as a URI parameter). This may not be possible
|
26
|
-
# providers.
|
22
|
+
# additional calls (if the user id is returned with the
|
23
|
+
# token or as a URI parameter). This may not be possible
|
24
|
+
# with all providers.
|
27
25
|
|
28
|
-
# Get the user id from raw info
|
29
26
|
uid { raw_info['sub'] }
|
30
27
|
|
31
28
|
info do
|
@@ -51,18 +48,51 @@ module OmniAuth
|
|
51
48
|
}.reject { |k, v| v.nil? }
|
52
49
|
end
|
53
50
|
|
51
|
+
def request_phase
|
52
|
+
add_openid
|
53
|
+
super
|
54
|
+
end
|
55
|
+
|
54
56
|
def raw_info
|
55
|
-
@raw_info ||= access_token.
|
57
|
+
@raw_info ||= decode_idtoken(access_token.params['id_token'])
|
58
|
+
request.update_param('sid', @raw_info['sid'])
|
59
|
+
@raw_info
|
56
60
|
end
|
57
61
|
|
58
|
-
# Over-ride callback_url definition to maintain
|
59
|
-
# compatibility with omniauth-oauth2 >= 1.4.0
|
60
|
-
#
|
61
|
-
# See: https://github.com/intridea/omniauth-oauth2/issues/81
|
62
62
|
def callback_url
|
63
|
-
# Fixes regression in omniauth-oauth2 v1.4.0 by https://github.com/intridea/omniauth-oauth2/commit/85fdbe117c2a4400d001a6368cc359d88f40abc7
|
64
63
|
options[:callback_url] || (full_host + script_name + callback_path)
|
65
64
|
end
|
65
|
+
|
66
|
+
def callback_phase
|
67
|
+
should_sign_out? ? sign_out_phase : super
|
68
|
+
end
|
69
|
+
|
70
|
+
def add_openid
|
71
|
+
unless options.scope.split.include? 'openid'
|
72
|
+
options.scope = options.scope.split.push('openid').join(' ')
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def decode_idtoken(idtoken)
|
77
|
+
@jwt_info = JWT.decode idtoken, nil, false
|
78
|
+
@jwt_info[0]
|
79
|
+
end
|
80
|
+
|
81
|
+
def should_sign_out?
|
82
|
+
request.post? && request.params.has_key?('logout_token')
|
83
|
+
end
|
84
|
+
|
85
|
+
def sign_out_phase
|
86
|
+
if options[:enable_remote_sign_out]
|
87
|
+
backchannel_logout_request.new(self, request).call(options)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def backchannel_logout_request
|
94
|
+
BackChannelLogoutRequest
|
95
|
+
end
|
66
96
|
end
|
67
97
|
end
|
68
|
-
end
|
98
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module OmniAuth
|
2
|
+
module Strategies
|
3
|
+
class Authentiq
|
4
|
+
class BackChannelLogoutRequest
|
5
|
+
|
6
|
+
def initialize(strategy, request)
|
7
|
+
@strategy, @request = strategy, request
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(options = {})
|
11
|
+
@options = options
|
12
|
+
|
13
|
+
begin
|
14
|
+
# for sign_out_callback.call(*back_channel_logout_request) to execute
|
15
|
+
# a proc must be set in the devise.rb initializer of the rails app
|
16
|
+
result = sign_out_callback.call(*back_channel_logout_request)
|
17
|
+
rescue StandardError => err
|
18
|
+
result = back_channel_logout_response(400, [err.to_s])
|
19
|
+
else
|
20
|
+
if result
|
21
|
+
result = back_channel_logout_response(200, ['Logout succeeded'])
|
22
|
+
else
|
23
|
+
result = back_channel_logout_response(501, ['Authentiq session does not exist'])
|
24
|
+
end
|
25
|
+
ensure
|
26
|
+
return unless result
|
27
|
+
return result.finish
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def back_channel_logout_request
|
34
|
+
@logout_request || begin
|
35
|
+
decode_logout_token(@request.params['logout_token'])
|
36
|
+
@request
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def decode_logout_token(logout_token)
|
41
|
+
begin
|
42
|
+
logout_jwt = JWT.decode logout_token, @options.client_secret, true, {
|
43
|
+
:algorithm => algorithm,
|
44
|
+
:iss => issuer,
|
45
|
+
:verify_iss => true,
|
46
|
+
:aud => @options.client_id,
|
47
|
+
:verify_aud => true,
|
48
|
+
:verify_iat => true,
|
49
|
+
:verify_jti => true,
|
50
|
+
:verify_sub => true,
|
51
|
+
:leeway => 60
|
52
|
+
}
|
53
|
+
if validate_events(logout_jwt[0]) && validate_nonce(logout_jwt[0]) && validate_sid(logout_jwt[0])
|
54
|
+
@request.update_param('sid', logout_jwt[0]['sid'])
|
55
|
+
else
|
56
|
+
raise 'Logout JWT validation failed. Missing session, events claim or nonce claim is present'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def validate_events(logout_jwt)
|
62
|
+
logout_jwt.key?('events') &&
|
63
|
+
(logout_jwt['events'][0] == 'http://schemas.openid.net/event/backchannel-logout' ||
|
64
|
+
logout_jwt['events'].key?('http://schemas.openid.net/event/backchannel-logout'))
|
65
|
+
end
|
66
|
+
|
67
|
+
def validate_nonce(logout_jwt)
|
68
|
+
!logout_jwt.key?('nonce')
|
69
|
+
end
|
70
|
+
|
71
|
+
def sign_out_callback
|
72
|
+
@options[:enable_remote_sign_out]
|
73
|
+
end
|
74
|
+
|
75
|
+
def validate_sid(logout_jwt)
|
76
|
+
logout_jwt.key?('sid')
|
77
|
+
end
|
78
|
+
|
79
|
+
def back_channel_logout_response(code, body)
|
80
|
+
response = Rack::Response.new
|
81
|
+
response.status = code
|
82
|
+
response['Cache-Control'] = 'no-cache, no-store'
|
83
|
+
response['Pragma'] = 'no-cache'
|
84
|
+
response.headers['Content-Type'] = 'text/plain; charset=utf-8'
|
85
|
+
response.body = body
|
86
|
+
response
|
87
|
+
end
|
88
|
+
|
89
|
+
def issuer
|
90
|
+
@options.issuer.nil? ? 'https://connect.authentiq.io/' : @options.issuer
|
91
|
+
end
|
92
|
+
|
93
|
+
def algorithm
|
94
|
+
if @options.algorithm != nil && (%w(HS256 RS256 ES256).include? @options.client_signed_response_alg)
|
95
|
+
@options.client_signed_response_alg
|
96
|
+
else
|
97
|
+
'HS256'
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: omniauth-authentiq
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alexandros Keramidas
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-02-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: omniauth-oauth2
|
@@ -48,6 +48,7 @@ files:
|
|
48
48
|
- lib/omniauth/authentiq.rb
|
49
49
|
- lib/omniauth/authentiq/version.rb
|
50
50
|
- lib/omniauth/strategies/authentiq.rb
|
51
|
+
- lib/omniauth/strategies/oidc/back_channel_logout_request.rb
|
51
52
|
- omniauth-authentiq.gemspec
|
52
53
|
homepage: https://github.com/AuthentiqID/omniauth-authentiq
|
53
54
|
licenses:
|