Class: CF::UAA::StubUAAConn
- Inherits:
-
Stub::Base
- Object
- Stub::Base
- CF::UAA::StubUAAConn
- Defined in:
- lib/uaa/stub/uaa.rb
Class Attribute Summary collapse
-
.authcode_store ⇒ Object
Returns the value of attribute authcode_store.
Attributes inherited from Stub::Base
#match, #reply, #request, #server
Instance Method Summary collapse
- #access_denied(msg = 'access denied') ⇒ Object
- #assign_auth_code(client_id, user_id, scope, redir_uri) ⇒ Object
- #auth_client(basic_auth_header) ⇒ Object
-
#bad_params?(params, required, optional = nil) ⇒ Boolean
if required and optional arrays are given, extra params are an error.
- #bad_request(msg = nil) ⇒ Object
-
#calc_scope(client, user, requested_scope) ⇒ Object
returns granted scopes TODO: doesn’t handle actual user authorization yet.
-
#client_to_scim(info) ⇒ Object
—————————————————————————- client endpoints.
- #decode_cookie(str) ⇒ Object
-
#default_route ⇒ Object
—————————————————————————- miscellaneous endpoints.
- #encode_cookie(obj = {}) ⇒ Object
- #find_user(name, pwd = nil) ⇒ Object
- #ids_to_names(ids) ⇒ Object
- #inject_error(input = nil) ⇒ Object
- #names_to_ids(names, rtype) ⇒ Object
- #not_found(name = nil) ⇒ Object
- #obj_access?(rtype, oid, perm) ⇒ Boolean
- #page_query(rtype, query, attrs, acl = nil, acl_id = nil) ⇒ Object
- #primary_email(emails) ⇒ Object
- #redeem_auth_code(client_id, redir_uri, code) ⇒ Object
- #redir_err_f(cburi, state, msg) ⇒ Object
- #redir_err_q(cburi, state, msg) ⇒ Object
- #redir_with_fragment(cburi, params) ⇒ Object
- #redir_with_query(cburi, params) ⇒ Object
- #sanitize_int(arg, default, min, max = nil) ⇒ Object
- #scim_to_client(info) ⇒ Object
-
#token_reply_info(client, scope, user = nil, state = nil, refresh = false) ⇒ Object
current uaa token contents: exp, user_name, scope, email, user_id, client_id, client_authorities, user_authorities.
- #valid_redir_uri?(client, redir_uri) ⇒ Boolean
- #valid_token(accepted_scope) ⇒ Object
Methods inherited from Stub::Base
find_route, #initialize, #process, #reply_in_kind, route
Constructor Details
This class inherits a constructor from Stub::Base
Class Attribute Details
.authcode_store ⇒ Object
Returns the value of attribute authcode_store.
278 279 280 |
# File 'lib/uaa/stub/uaa.rb', line 278 def authcode_store @authcode_store end |
Instance Method Details
#access_denied(msg = 'access denied') ⇒ Object
36 |
# File 'lib/uaa/stub/uaa.rb', line 36 def access_denied(msg = 'access denied') reply_in_kind(403, error: 'access_denied', error_description: msg) end |
#assign_auth_code(client_id, user_id, scope, redir_uri) ⇒ Object
279 280 281 282 283 284 285 |
# File 'lib/uaa/stub/uaa.rb', line 279 def assign_auth_code(client_id, user_id, scope, redir_uri) code = SecureRandom.base64(8) raise 'authcode collision' if self.class.authcode_store[code] self.class.authcode_store[code] = {client_id: client_id, user_id: user_id, scope: scope, redir_uri: redir_uri} code end |
#auth_client(basic_auth_header) ⇒ Object
168 169 170 171 172 173 174 175 |
# File 'lib/uaa/stub/uaa.rb', line 168 def auth_client(basic_auth_header) ah = basic_auth_header.split(' ') return unless ah[0] =~ /^basic$/i ah = Base64::strict_decode64(ah[1]).split(':') ah = ah.map { |item| CGI::unescape(item) } client = server.scim.get_by_name(ah[0], :client) client if client && client[:client_secret] == ah[1] end |
#bad_params?(params, required, optional = nil) ⇒ Boolean
if required and optional arrays are given, extra params are an error
260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/uaa/stub/uaa.rb', line 260 def bad_params?(params, required, optional = nil) required.each {|r| next if params[r] reply.json(400, error: 'invalid_request', error_description: "no #{r} in request") return true } return false unless optional params.each {|k, v| next if required.include?(k) || optional.include?(k) reply.json(400, error: 'invalid_request', error_description: "#{k} not allowed") return true } false end |
#bad_request(msg = nil) ⇒ Object
34 |
# File 'lib/uaa/stub/uaa.rb', line 34 def bad_request(msg = nil); reply_in_kind(400, error: "bad request#{msg ? ',' : ''} #{msg}") end |
#calc_scope(client, user, requested_scope) ⇒ Object
returns granted scopes TODO: doesn’t handle actual user authorization yet
206 207 208 209 210 211 212 213 |
# File 'lib/uaa/stub/uaa.rb', line 206 def calc_scope(client, user, requested_scope) possible_scope = ids_to_names(client[user ? :scope : :authorities]) requested_scope = Util.arglist(requested_scope) || [] return unless (requested_scope - possible_scope).empty? requested_scope = possible_scope if requested_scope.empty? granted_scopes = user ? (ids_to_names(user[:groups]) & requested_scope) : requested_scope # handle auto-deny Util.strlist(granted_scopes) unless granted_scopes.empty? end |
#client_to_scim(info) ⇒ Object
client endpoints
356 357 358 359 |
# File 'lib/uaa/stub/uaa.rb', line 356 def client_to_scim(info) ['authorities', 'scope', 'autoapprove'].each { |a| info[a] = names_to_ids(info[a], :group) if info.key?(a) } info end |
#decode_cookie(str) ⇒ Object
40 |
# File 'lib/uaa/stub/uaa.rb', line 40 def (str) Util.json.decode64(str) end |
#default_route ⇒ Object
miscellaneous endpoints
66 |
# File 'lib/uaa/stub/uaa.rb', line 66 def default_route; reply_in_kind(404, error: 'not found', error_description: "unknown path #{request.path}") end |
#encode_cookie(obj = {}) ⇒ Object
39 |
# File 'lib/uaa/stub/uaa.rb', line 39 def (obj = {}) Util.json_encode64(obj) end |
#find_user(name, pwd = nil) ⇒ Object
57 58 59 60 |
# File 'lib/uaa/stub/uaa.rb', line 57 def find_user(name, pwd = nil) user = server.scim.get_by_name(name, :user, :password, :id, :emails, :username, :groups) user if user && (!pwd || user[:password] == pwd) end |
#ids_to_names(ids) ⇒ Object
37 |
# File 'lib/uaa/stub/uaa.rb', line 37 def ids_to_names(ids); ids ? ids.map { |id| server.scim.name(id) } : [] end |
#inject_error(input = nil) ⇒ Object
25 26 27 28 29 30 31 32 |
# File 'lib/uaa/stub/uaa.rb', line 25 def inject_error(input = nil) case server.reply_badly when :non_json then reply.text('non-json reply') when :bad_json then reply.body = '{"access_token":"good.access.token" "missed a comma":"there"}' when :bad_state then input[:state] = 'badstate' when :no_token_type then input.delete(:token_type) end end |
#names_to_ids(names, rtype) ⇒ Object
38 |
# File 'lib/uaa/stub/uaa.rb', line 38 def names_to_ids(names, rtype); names ? names.map { |name| server.scim.id(name, rtype) } : [] end |
#not_found(name = nil) ⇒ Object
35 |
# File 'lib/uaa/stub/uaa.rb', line 35 def not_found(name = nil); reply_in_kind(404, error: "#{name} not found") end |
#obj_access?(rtype, oid, perm) ⇒ Boolean
435 436 437 438 439 440 441 |
# File 'lib/uaa/stub/uaa.rb', line 435 def obj_access?(rtype, oid, perm) major_scope = perm == :writers ? 'scim.write' : 'scim.read' return unless tkn = valid_token("#{major_scope} scim.me") return tkn if tkn['scope'].include?(major_scope) || rtype == :group && server.scim.is_member(oid, tkn['user_id'], perm) access_denied end |
#page_query(rtype, query, attrs, acl = nil, acl_id = nil) ⇒ Object
502 503 504 505 506 507 508 509 510 511 512 513 514 |
# File 'lib/uaa/stub/uaa.rb', line 502 def page_query(rtype, query, attrs, acl = nil, acl_id = nil) if query['attributes'] attrs = attrs & Util.arglist(query['attributes']).each_with_object([]) {|a, o| o << a.to_sym if StubScim::ATTR_NAMES.include?(a = a.downcase) } end start = sanitize_int(query['startindex'], 1, 1) count = sanitize_int(query['count'], 15, 1, 3000) return bad_request('invalid startIndex or count') unless start && count info, total = server.scim.find(rtype, start: start - 1, count: count, filter: query['filter'], attrs: attrs, acl: acl, acl_id: acl_id) reply_in_kind(resources: info, itemsPerPage: info.length, startIndex: start, totalResults: total) end |
#primary_email(emails) ⇒ Object
50 51 52 53 54 55 |
# File 'lib/uaa/stub/uaa.rb', line 50 def primary_email(emails) return unless emails emails.each {|e| return e[:value] if e[:type] && e[:type] == 'primary' } emails[0][:value] end |
#redeem_auth_code(client_id, redir_uri, code) ⇒ Object
286 287 288 289 290 |
# File 'lib/uaa/stub/uaa.rb', line 286 def redeem_auth_code(client_id, redir_uri, code) return unless info = self.class.authcode_store.delete(code) return unless info[:client_id] == client_id && info[:redir_uri] == redir_uri [info[:user_id], info[:scope]] end |
#redir_err_f(cburi, state, msg) ⇒ Object
201 |
# File 'lib/uaa/stub/uaa.rb', line 201 def redir_err_f(cburi, state, msg); redir_with_fragment(cburi, error: msg, state: state) end |
#redir_err_q(cburi, state, msg) ⇒ Object
202 |
# File 'lib/uaa/stub/uaa.rb', line 202 def redir_err_q(cburi, state, msg); redir_with_query(cburi, error: msg, state: state) end |
#redir_with_fragment(cburi, params) ⇒ Object
187 188 189 190 191 192 |
# File 'lib/uaa/stub/uaa.rb', line 187 def redir_with_fragment(cburi, params) reply.status = 302 uri = URI.parse(cburi) uri.fragment = Util.encode_form(params) reply.headers[:location] = uri.to_s end |
#redir_with_query(cburi, params) ⇒ Object
194 195 196 197 198 199 |
# File 'lib/uaa/stub/uaa.rb', line 194 def redir_with_query(cburi, params) reply.status = 302 uri = URI.parse(cburi) uri.query = Util.encode_form(params) reply.headers[:location] = uri.to_s end |
#sanitize_int(arg, default, min, max = nil) ⇒ Object
496 497 498 499 500 |
# File 'lib/uaa/stub/uaa.rb', line 496 def sanitize_int(arg, default, min, max = nil) return default if arg.nil? return unless arg.to_i.to_s == arg && (i = arg.to_i) >= min max && i > max ? max : i end |
#scim_to_client(info) ⇒ Object
361 362 363 364 365 |
# File 'lib/uaa/stub/uaa.rb', line 361 def scim_to_client(info) [:authorities, :scope, :autoapprove].each { |a| info[a] = ids_to_names(info[a]) if info.key?(a) } info.delete(:id) info end |
#token_reply_info(client, scope, user = nil, state = nil, refresh = false) ⇒ Object
current uaa token contents: exp, user_name, scope, email, user_id,
client_id, client_authorities, user_authorities
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/uaa/stub/uaa.rb', line 151 def token_reply_info(client, scope, user = nil, state = nil, refresh = false) interval = client[:access_token_validity] || 3600 token_body = { jti: SecureRandom.uuid, aud: scope, scope: scope, client_id: client[:client_id], exp: interval + Time.now.to_i } if user token_body[:user_id] = user[:id] token_body[:email] = primary_email(user[:emails]) token_body[:user_name] = user[:username] end info = { access_token: TokenCoder.encode(token_body, :algorithm => 'none'), token_type: 'bearer', expires_in: interval, scope: scope} info[:state] = state if state info[:refresh_token] = 'universal_refresh_token' if refresh inject_error(info) info end |
#valid_redir_uri?(client, redir_uri) ⇒ Boolean
177 178 179 180 181 182 183 184 185 |
# File 'lib/uaa/stub/uaa.rb', line 177 def valid_redir_uri?(client, redir_uri) t = URI.parse(redir_uri) return true unless (ruris = client[:redirect_uris]) && !ruris.empty? false unless ruris.each { |reg_uri| r = URI.parse(reg_uri) return true if r.scheme == t.scheme && r.host == t.host && (!r.port || r.port == t.port) && (!r.path || r.path == t.path) } end |
#valid_token(accepted_scope) ⇒ Object
42 43 44 45 46 47 48 |
# File 'lib/uaa/stub/uaa.rb', line 42 def valid_token(accepted_scope) return nil unless (ah = request.headers['authorization']) && (ah = ah.split(' '))[0] =~ /^bearer$/i contents = TokenCoder.decode(ah[1], accept_algorithms: 'none') contents['scope'], accepted_scope = Util.arglist(contents['scope']), Util.arglist(accepted_scope) return contents if accepted_scope.nil? || !(accepted_scope & contents['scope']).empty? access_denied("accepted scope #{Util.strlist(accepted_scope)}") end |