Class: CF::UAA::StubUAAConn
- Inherits:
-
Stub::Base
- Object
- Stub::Base
- CF::UAA::StubUAAConn
- Defined in:
- lib/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.
270 271 272 |
# File 'lib/stub/uaa.rb', line 270 def authcode_store @authcode_store end |
Instance Method Details
#access_denied(msg = "access denied") ⇒ Object
35 |
# File 'lib/stub/uaa.rb', line 35 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
271 272 273 274 275 276 277 |
# File 'lib/stub/uaa.rb', line 271 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
161 162 163 164 165 166 167 |
# File 'lib/stub/uaa.rb', line 161 def auth_client(basic_auth_header) ah = basic_auth_header.split(' ') return unless ah[0] =~ /^basic$/i ah = Base64::strict_decode64(ah[1]).split(':') 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
252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
# File 'lib/stub/uaa.rb', line 252 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
33 |
# File 'lib/stub/uaa.rb', line 33 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
198 199 200 201 202 203 204 205 |
# File 'lib/stub/uaa.rb', line 198 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
339 340 341 342 |
# File 'lib/stub/uaa.rb', line 339 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
39 |
# File 'lib/stub/uaa.rb', line 39 def (str) Util.json.decode64(str) end |
#default_route ⇒ Object
miscellaneous endpoints
64 |
# File 'lib/stub/uaa.rb', line 64 def default_route; reply_in_kind(404, error: "not found", error_description: "unknown path #{request.path}") end |
#encode_cookie(obj = {}) ⇒ Object
38 |
# File 'lib/stub/uaa.rb', line 38 def (obj = {}) Util.json_encode64(obj) end |
#find_user(name, pwd = nil) ⇒ Object
55 56 57 58 |
# File 'lib/stub/uaa.rb', line 55 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
36 |
# File 'lib/stub/uaa.rb', line 36 def ids_to_names(ids); ids ? ids.map { |id| server.scim.name(id) } : [] end |
#inject_error(input = nil) ⇒ Object
24 25 26 27 28 29 30 31 |
# File 'lib/stub/uaa.rb', line 24 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
37 |
# File 'lib/stub/uaa.rb', line 37 def names_to_ids(names, rtype); names ? names.map { |name| server.scim.id(name, rtype) } : [] end |
#not_found(name = nil) ⇒ Object
34 |
# File 'lib/stub/uaa.rb', line 34 def not_found(name = nil); reply_in_kind(404, error: "#{name} not found") end |
#obj_access?(rtype, oid, perm) ⇒ Boolean
406 407 408 409 410 411 412 |
# File 'lib/stub/uaa.rb', line 406 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
433 434 435 436 437 438 439 440 441 442 443 444 445 |
# File 'lib/stub/uaa.rb', line 433 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
49 50 51 52 53 |
# File 'lib/stub/uaa.rb', line 49 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
278 279 280 281 282 |
# File 'lib/stub/uaa.rb', line 278 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
193 |
# File 'lib/stub/uaa.rb', line 193 def redir_err_f(cburi, state, msg); redir_with_fragment(cburi, error: msg, state: state) end |
#redir_err_q(cburi, state, msg) ⇒ Object
194 |
# File 'lib/stub/uaa.rb', line 194 def redir_err_q(cburi, state, msg); redir_with_query(cburi, error: msg, state: state) end |
#redir_with_fragment(cburi, params) ⇒ Object
179 180 181 182 183 184 |
# File 'lib/stub/uaa.rb', line 179 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
186 187 188 189 190 191 |
# File 'lib/stub/uaa.rb', line 186 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
427 428 429 430 431 |
# File 'lib/stub/uaa.rb', line 427 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
344 345 346 347 348 |
# File 'lib/stub/uaa.rb', line 344 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
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
# File 'lib/stub/uaa.rb', line 144 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
169 170 171 172 173 174 175 176 177 |
# File 'lib/stub/uaa.rb', line 169 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
41 42 43 44 45 46 47 |
# File 'lib/stub/uaa.rb', line 41 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 |