Ravn::Tactical::Auth::
PublicKeyScheme
module
Implementation of bearer authentication using the keypairs of the kit’s nodes instead of a shared secret.
- TOKEN_PATTERN
The format of a valid bearer auth token
authentication_failure( reason )
Convenience method for logging a reason
authentication failed before returning nil.
121 def self::authentication_failure( reason )
122 self.log.error "Authentication failure: %s" % [ reason ]
123 return nil
124 end
authorization_failure( reason )
Convenience method for logging a reason
authorization failed before returning nil
.
128 def self::authorization_failure( reason )
129 self.log.error "Authorization failure: %s" % [ reason ]
130 return nil
131 end
check_auth_claims( ciphertext, node, request, **options )
Decrypt the token from the provided ciphertext
using the given node
‘s public key and check that the claims match the given request
. Returns true if the token decrypts and its claims match, otherwise return nil
after logging at error level.
92 def self::check_auth_claims( ciphertext, node, request, **options )
93 secret_key = options[:secret_key] || Ravn::Crypto.key
94 claims = Ravn::Tactical::Auth.
95 decode_token( ciphertext, node.public_key, secret_key: secret_key ) or
96 return authentication_failure( 'Token could not be decoded.' )
97
98 self.log.debug "Token claims: %p" % [ claims ]
99 return authentication_failure( 'Token claims is not a Hash' ) unless claims.is_a?( Hash )
100
101 claimed_control = claims[ :req ] or
102 return authentication_failure( 'Token claims is missing required element `req`.' )
103 request_control = "%s %s %s" % [
104 request.request_method,
105 request.fullpath,
106 request.get_header('SERVER_PROTOCOL')
107 ]
108 unless request_control == claimed_control
109 return authentication_failure 'Req claim %p does not match %p' %
110 [ claimed_control, request_control ]
111 end
112
113
114
115 return true
116 end
check_auth_credentials( credentials, request, ** )
Validate the auth credentials
against the incoming request
and return the device_id and encrypted token if successful. Returns nil
after logging at error level if there’s a problem.
74 def self::check_auth_credentials( credentials, request, ** )
75 self.log.info "Checking authentication for %s: %p" % [ request.url, credentials ]
76 auth_token = credentials[:auth_token] or return authentication_failure( 'No auth token' )
77
78 device_id, ciphertext = auth_token.split( '.' )
79 return authentication_failure( 'Token has no device ID' ) unless
80 device_id && !device_id.empty?
81 return authentication_failure( 'Token has no ciphertext' ) unless
82 ciphertext && !ciphertext.empty?
83
84 return device_id, ciphertext
85 end
check_authentication( credentials, request, **options )
Check the authentication for request
provided by the given credentials
. Returns the authenticaated Ravn::Tactical::Node
on success, nil
on failure.
49 def self::check_authentication( credentials, request, **options )
50 device_id, ciphertext = self.check_auth_credentials( credentials, request, **options )
51 return nil unless device_id
52 node = Ravn::Tactical::Node.undeleted.by_device_id( device_id ).first or
53 return authentication_failure 'No such node %s' % [ device_id ]
54
55 self.check_auth_claims( ciphertext, node, request, **options ) or return nil
56
57 return node
58 end
check_authorization( identity, request, **options )
Check the authorization for the given request
to ensure the provided identity
should be able to access the resource. Returns true
if it is authorized.
63 def self::check_authorization( identity, request, **options )
64 self.log.info "Checking authorization for %s: %p" % [ request.url, identity ]
65 return authorization_failure( "identity is not a node" ) unless identity.respond_to?( :is_control? )
66 return authorization_failure( "node is not the Control" ) unless identity.is_control?
67 return true
68 end
valid?( credentials, request, **options )
Returns true
if this scheme can be used to authenticate the given request
and options
.
39 def self::valid?( credentials, request, **options )
40 self.log.debug "validating the public key auth for credentials: %p" % [ credentials ]
41 credentials[:auth_scheme] == 'Bearer' &&
42 credentials[:auth_token] &&
43 credentials[:auth_token].match?( TOKEN_PATTERN )
44 end