Skip to content
Extraits de code Groupes Projets
Valider 0fbcb712 rédigé par theworldbright's avatar theworldbright
Parcourir les fichiers

Add support for request_uri and claims

parent 2a002d90
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
Affichage de avec 112 ajouts et 21 suppressions
......@@ -76,10 +76,22 @@ module Api
end
def request_authorization_consent_form
add_claims_to_scopes
endpoint = Api::OpenidConnect::AuthorizationPoint::EndpointStartPoint.new(current_user)
handle_start_point_response(endpoint)
end
def add_claims_to_scopes
return unless params[:claims]
claims_json = JSON.parse(params[:claims])
return unless claims_json
claims_array = claims_json["userinfo"].try(:keys)
return unless claims_array
claims = claims_array.join(" ")
req = build_rack_request
req.update_param("scope", req[:scope] + " " + claims)
end
def logged_in_before?(seconds)
if seconds.nil?
false
......@@ -112,14 +124,12 @@ module Api
end
def save_params_and_render_consent_form(endpoint)
@o_auth_application, @response_type, @redirect_uri, @scopes, @request_object = *[
@o_auth_application, @response_type, @redirect_uri, @scopes = *[
endpoint.o_auth_application, endpoint.response_type,
endpoint.redirect_uri, endpoint.scopes, endpoint.request_object
endpoint.redirect_uri, endpoint.scopes
]
save_request_parameters
@app = UserApplicationPresenter.new @o_auth_application, @scopes
render :new
end
......@@ -128,7 +138,6 @@ module Api
session[:response_type] = @response_type
session[:redirect_uri] = @redirect_uri
session[:scopes] = scopes_as_space_seperated_values
session[:request_object] = @request_object
session[:nonce] = params[:nonce]
end
......@@ -153,7 +162,6 @@ module Api
session.delete(:response_type)
session.delete(:redirect_uri)
session.delete(:scopes)
session.delete(:request_object)
session.delete(:nonce)
end
......@@ -167,7 +175,6 @@ module Api
req.update_param("redirect_uri", session[:redirect_uri])
req.update_param("response_type", response_type_as_space_seperated_values)
req.update_param("scope", session[:scopes])
req.update_param("request_object", session[:request_object])
req.update_param("nonce", session[:nonce])
end
......
......@@ -22,11 +22,14 @@ module Api
jwks_uri: api_openid_connect_url,
scopes_supported: Api::OpenidConnect::Authorization::SCOPES,
response_types_supported: Api::OpenidConnect::OAuthApplication.available_response_types,
request_object_signing_alg_values_supported: %i(HS256 HS384 HS512),
request_object_signing_alg_values_supported: %i(none),
request_parameter_supported: true,
request_uri_parameter_supported: true,
subject_types_supported: %w(public pairwise),
id_token_signing_alg_values_supported: %i(RS256),
token_endpoint_auth_methods_supported: %w(client_secret_basic client_secret_post private_key_jwt),
claims_supported: %w(sub nickname profile picture)
claims_parameter_supported: true,
claims_supported: %w(sub name nickname profile picture)
)
end
end
......
......@@ -8,7 +8,13 @@ module Api
end
def show
render json: current_user, serializer: UserInfoSerializer, authorization: current_token.authorization
serializer = UserInfoSerializer.new(current_user)
auth = current_token.authorization
serializer.serialization_options = { authorization: auth }
attributes_without_essential = serializer.attributes.with_indifferent_access.select{|scope| auth.scopes.include? scope }
attributes = attributes_without_essential.merge(
sub: serializer.sub)
render json: attributes.to_json
end
def current_user
......
......@@ -17,7 +17,7 @@ module Api
scope :with_redirect_uri, ->(given_uri) { where redirect_uri: given_uri }
SCOPES = %w(openid read write)
SCOPES = %w(openid sub aud name nickname profile picture read write)
def setup
self.refresh_token = SecureRandom.hex(32)
......
class UserInfoSerializer < ActiveModel::Serializer
attributes :sub, :nickname, :profile, :picture
attributes :sub, :name, :nickname, :profile, :picture
def sub
auth = serialization_options[:authorization]
Api::OpenidConnect::SubjectIdentifierCreator.createSub(auth)
end
def name
(object.first_name || "") + (object.last_name || "")
end
def nickname
object.name
end
......
......@@ -3,12 +3,13 @@ module Api
module AuthorizationPoint
class Endpoint
attr_accessor :app, :user, :o_auth_application, :redirect_uri, :response_type,
:scopes, :_request_, :request_uri, :request_object, :nonce
:scopes, :request_uri, :request_object, :nonce
delegate :call, to: :app
def initialize(user)
@user = user
@app = Rack::OAuth2::Server::Authorize.new do |req, res|
build_from_request_object(req)
build_attributes(req, res)
if OAuthApplication.available_response_types.include? Array(req.response_type).join(" ")
handle_response_type(req, res)
......@@ -29,10 +30,6 @@ module Api
raise NotImplementedError # Implemented by subclass
end
def scopes
Api::OpenidConnect::Authorization::SCOPES
end
private
def build_client(req)
......@@ -48,12 +45,17 @@ module Api
end
def build_scopes(req)
replace_profile_scope_with_specific_claims(req)
@scopes = req.scope.map {|scope|
scope.tap do |scope_name|
req.invalid_scope! "Unknown scope: #{scope_name}" unless scopes.include? scope_name
req.invalid_scope! "Unknown scope: #{scope_name}" unless auth_scopes.include? scope_name
end
}
end
def auth_scopes
Api::OpenidConnect::Authorization::SCOPES
end
end
end
end
......
......@@ -19,6 +19,14 @@ module Api
end
end
def replace_profile_scope_with_specific_claims(req)
# Empty
end
def build_from_request_object(req)
# Empty
end
private
def approved!(req, res)
......
......@@ -2,9 +2,35 @@ module Api
module OpenidConnect
module AuthorizationPoint
class EndpointStartPoint < Endpoint
def build_from_request_object(req)
request_object = build_request_object(req)
return unless request_object
claims = request_object.raw_attributes.with_indifferent_access[:claims].try(:[], :userinfo).try(:keys)
return unless claims
req.update_param("scope", req.scope + claims)
end
def handle_response_type(req, _res)
@response_type = req.response_type
end
def replace_profile_scope_with_specific_claims(req)
profile_claims = %w(sub aud name nickname profile picture)
scopes_as_claims = req.scope.map { |scope| scope == "profile" ? profile_claims : [scope] }.flatten!.uniq
req.update_param("scope", scopes_as_claims)
end
private
def build_request_object(req)
if req.request_uri.present?
OpenIDConnect::RequestObject.fetch req.request_uri
elsif req.request.present?
OpenIDConnect::RequestObject.decode req.request
else
nil
end
end
end
end
end
......
......@@ -22,6 +22,41 @@ describe Api::OpenidConnect::AuthorizationsController, type: :controller do
end
end
context "using claims" do
it "should return a form page" do
get :new, client_id: client.client_id, redirect_uri: "http://localhost:3000/", response_type: "id_token",
scope: "openid", claims: "{\"userinfo\": {\"name\": {\"essential\": true}}}", nonce: SecureRandom.hex(16),
state: SecureRandom.hex(16)
expect(response.body).to match("Diaspora Test Client")
end
end
context "as a request object" do
it "should return a form page" do
header = JWT.encoded_header("none")
payload_hash = { client_id: client.client_id, redirect_uri: "http://localhost:3000/", response_type: "id_token",
scope: "openid", nonce: "hello", state: "hello", claims: { userinfo: { name: { essential: true } } } }
payload = JWT.encoded_payload(JSON.parse(payload_hash.to_json))
request_object = header + "." + payload + "."
get :new, client_id: client.client_id, redirect_uri: "http://localhost:3000/", response_type: "id_token",
scope: "openid", nonce: "hello", state: "hello", request: request_object
expect(response.body).to match("Diaspora Test Client")
end
end
context "as a request object with no claims" do
it "should return a form page" do
header = JWT.encoded_header("none")
payload_hash = { client_id: client.client_id, redirect_uri: "http://localhost:3000/",
response_type: "id_token", scope: "openid", nonce: "hello", state: "hello" }
payload = JWT.encoded_payload(JSON.parse(payload_hash.to_json))
request_object = header + "." + payload + "."
get :new, client_id: client.client_id, redirect_uri: "http://localhost:3000/", response_type: "id_token",
scope: "openid", nonce: "hello", state: "hello", request: request_object
expect(response.body).to match("Diaspora Test Client")
end
end
context "as POST request" do
it "should return a form page" do
post :new, client_id: client.client_id, redirect_uri: "http://localhost:3000/", response_type: "id_token",
......
......@@ -348,19 +348,19 @@ FactoryGirl.define do
factory :auth_with_read, class: Api::OpenidConnect::Authorization do
o_auth_application
user
scopes %w(openid read)
scopes %w(openid sub aud profile picture nickname name read)
end
factory :auth_with_read_and_ppid, class: Api::OpenidConnect::Authorization do
association :o_auth_application, factory: :o_auth_application_with_ppid
user
scopes %w(openid read)
scopes %w(openid sub aud profile picture nickname name read)
end
factory :auth_with_read_and_write, class: Api::OpenidConnect::Authorization do
o_auth_application
user
scopes %w(openid read write)
scopes %w(openid sub aud profile picture nickname name read write)
end
# Factories for the DiasporaFederation-gem
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter