From 2ca4f7887978bbb16062e89f8a4d2e5e4be4efb4 Mon Sep 17 00:00:00 2001 From: Masakiyo Morikawa Date: Wed, 2 Apr 2025 14:33:54 +0900 Subject: [PATCH 1/2] v3 support --- lib/authlete/api.rb | 306 ++++++++++++++++++++++-------------- lib/authlete/api_path/v2.rb | 206 ++++++++++++++++++++++++ lib/authlete/api_path/v3.rb | 211 +++++++++++++++++++++++++ 3 files changed, 609 insertions(+), 114 deletions(-) create mode 100644 lib/authlete/api_path/v2.rb create mode 100644 lib/authlete/api_path/v3.rb diff --git a/lib/authlete/api.rb b/lib/authlete/api.rb index db72287..3db4310 100644 --- a/lib/authlete/api.rb +++ b/lib/authlete/api.rb @@ -18,28 +18,75 @@ require 'json' require 'rack' require 'rest-client' - +require 'uri' +require_relative 'api_path/v2' +require_relative 'api_path/v3' module Authlete class Api include Authlete::Utility + module ApiVersion + V2 = :v2 + V3 = :v3 + + def self.from_string(version_string) + case version_string&.downcase + when 'v3' + V3 + else + # Defaults to V2 when the provided API version is not recognized or missing. + V2 + end + end + end + attr_accessor :host attr_accessor :service_owner_api_key attr_accessor :service_owner_api_secret attr_accessor :service_api_key attr_accessor :service_api_secret + attr_accessor :organization_access_token + attr_accessor :service_access_token + attr_accessor :service_id attr_accessor :extra_headers + attr_reader :api_version private + attr_reader :path_resolver + def initialize(config = {}) - @host = config[:host] - @service_owner_api_key = config[:service_owner_api_key] - @service_owner_api_secret = config[:service_owner_api_secret] - @service_api_key = config[:service_api_key] - @service_api_secret = config[:service_api_secret] - @extra_headers = nil + @host = config[:host] + # v2 + @service_owner_api_key = config[:service_owner_api_key] + @service_owner_api_secret = config[:service_owner_api_secret] + @service_api_key = config[:service_api_key] + @service_api_secret = config[:service_api_secret] + # v3 + @organization_access_token = config[:organization_access_token] + @service_access_token = config[:service_access_token] + @service_id = if config[:service_id].nil? || config[:service_id].to_s.empty? + nil + else + URI.encode_www_form_component(config[:service_id].to_s) + end + + @extra_headers = nil + @api_version = ApiVersion.from_string(config[:api_version]) + + if @api_version == ApiVersion::V3 && @service_id.nil? + warn "Warning: A Service ID (:service_id) is required for most APIs in Authlete version 3." + end + + @path_resolver = case @api_version + when ApiVersion::V3 + Authlete::ApiPath::V3.new(@service_id) + when ApiVersion::V2 + Authlete::ApiPath::V2.new() + else + raise ArgumentError, "Unsupported API version for path resolver: #{@api_version.inspect}" + end configure_logging(config[:rest_client_logging_level]) end @@ -59,8 +106,29 @@ def configure_logging(level) end end - def call_api(method, path, content_type, payload, user, password) + def call_api(method, path, content_type, payload, credential_type) headers = {} + user = nil + password = nil + token = nil + + case @api_version + when ApiVersion::V3 + token = case credential_type + when :service_owner then @organization_access_token + when :service then @service_access_token + else nil + end + headers.merge!(Authorization: "Bearer #{token}") unless token.nil? + when ApiVersion::V2 + user, password = case credential_type + when :service_owner then [@service_owner_api_key, @service_owner_api_secret] + when :service then [@service_api_key, @service_api_secret] + else [nil, nil] + end + else + raise ArgumentError, "Unsupported API version: #{@api_version.inspect}" + end headers.merge!(content_type: content_type) unless content_type.nil? @@ -146,23 +214,23 @@ def on_general_exception(exception) end def call_api_service_owner(method, path, content_type, payload) - call_api(method, path, content_type, payload, @service_owner_api_key, @service_owner_api_secret) + call_api(method, path, content_type, payload, :service_owner) end def call_api_service(method, path, content_type, payload) - call_api(method, path, content_type, payload, @service_api_key, @service_api_secret) + call_api(method, path, content_type, payload, :service) end - def call_api_json(path, body, user, password) - call_api(:post, path, 'application/json;charset=UTF-8', JSON.generate(body), user, password) + def call_api_json(path, body, credential_type) + call_api(:post, path, 'application/json;charset=UTF-8', JSON.generate(body), credential_type) end def call_api_json_service_owner(path, body) - call_api_json(path, body, @service_owner_api_key, @service_owner_api_secret) + call_api_json(path, body, :service_owner) end def call_api_json_service(path, body) - call_api_json(path, body, @service_api_key, @service_api_secret) + call_api_json(path, body, :service) end def build_error_message(path, exception) @@ -199,294 +267,304 @@ def extract_requestable_scopes(hash) public def authorization(request) - hash = call_api_json_service("/api/auth/authorization", to_hash(request)) - + path = @path_resolver.authorization + hash = call_api_json_service(path, to_hash(request)) Authlete::Model::Response::AuthorizationResponse.new(hash) end def authorization_issue(request) - hash = call_api_json_service("/api/auth/authorization/issue", to_hash(request)) - + path = @path_resolver.authorization_issue + hash = call_api_json_service(path, to_hash(request)) Authlete::Model::Response::AuthorizationIssueResponse.new(hash) end def authorization_fail(request) - hash = call_api_json_service("/api/auth/authorization/fail", to_hash(request)) - + path = @path_resolver.authorization_fail + hash = call_api_json_service(path, to_hash(request)) Authlete::Model::Response::AuthorizationFailResponse.new(hash) end def token(request) - hash = call_api_json_service("/api/auth/token", to_hash(request)) - + path = @path_resolver.token + hash = call_api_json_service(path, to_hash(request)) Authlete::Model::Response::TokenResponse.new(hash) end def token_issue(request) - hash = call_api_json_service("/api/auth/token/issue", to_hash(request)) - + path = @path_resolver.token_issue + hash = call_api_json_service(path, to_hash(request)) Authlete::Model::Response::TokenIssueResponse.new(hash) end def token_fail(request) - hash = call_api_json_service("/api/auth/token/fail", to_hash(request)) - + path = @path_resolver.token_fail + hash = call_api_json_service(path, to_hash(request)) Authlete::Model::Response::TokenFailResponse.new(hash) end def token_revoke(request) - hash = call_api_json_service("/api/auth/token/revoke", to_hash(request)) - + path = @path_resolver.token_revoke + hash = call_api_json_service(path, to_hash(request)) Authlete::Model::Response::TokenRevokeResponse.new(hash) end def service_create(service) - hash = call_api_json_service_owner("/api/service/create", to_hash(service)) - + path = @path_resolver.service_create + hash = call_api_json_service_owner(path, to_hash(service)) Authlete::Model::Service.new(hash) end - def service_delete(api_key) - call_api_service_owner(:delete, "/api/service/delete/#{api_key}", nil, nil) + def service_delete(service_id) + path = @path_resolver.service_delete(service_id) + call_api_service_owner(:delete, path, nil, nil) end - def service_get(api_key) - hash = call_api_service_owner(:get, "/api/service/get/#{api_key}", nil, nil) - + def service_get(service_id) + path = @path_resolver.service_get(service_id) + hash = call_api_service_owner(:get, path, nil, nil) Authlete::Model::Service.new(hash) end def service_get_list(params = nil) - hash = call_api_service_owner(:get, "/api/service/get/list#{to_query(params)}", nil, nil) - + base_path = @path_resolver.service_get_list + relative_path = base_path + to_query(params) + hash = call_api_service_owner(:get, relative_path, nil, nil) Authlete::Model::Response::ServiceListResponse.new(hash) end - def service_update(api_key, service) - hash = call_api_json_service_owner("/api/service/update/#{api_key}", to_hash(service)) - + def service_update(service_id, service) + path = @path_resolver.service_update(service_id) + hash = call_api_json_service_owner(path, to_hash(service)) Authlete::Model::Service.new(hash) end def serviceowner_get_self - hash = call_api_service_owner(:get, "/api/serviceowner/get/self", nil, nil) - + path = @path_resolver.serviceowner_get_self + hash = call_api_service_owner(:get, path, nil, nil) Authlete::Model::ServiceOwner.new(hash) end def client_create(client) - hash = call_api_json_service("/api/client/create", to_hash(client)) - + path = @path_resolver.client_create + hash = call_api_json_service(path, to_hash(client)) Authlete::Model::Client.new(hash) end def client_delete(client_id) - call_api_service(:delete, "/api/client/delete/#{client_id}", nil, nil) + path = @path_resolver.client_delete(client_id) + call_api_service(:delete, path, nil, nil) end def client_get(client_id) - hash = call_api_service(:get, "/api/client/get/#{client_id}", nil, nil) - + path = @path_resolver.client_get(client_id) + hash = call_api_service(:get, path, nil, nil) Authlete::Model::Client.new(hash) end def client_get_list(params = nil) - hash = call_api_service(:get, "/api/client/get/list#{to_query(params)}", nil, nil) - + base_path = @path_resolver.client_get_list + relative_path = base_path + to_query(params) + hash = call_api_service(:get, relative_path, nil, nil) Authlete::Model::Response::ClientListResponse.new(hash) end def client_update(client) - hash = call_api_json_service("/api/client/update/#{client.clientId}", to_hash(client)) - + path = @path_resolver.client_update(client.clientId) + hash = call_api_json_service(path, to_hash(client)) Authlete::Model::Client.new(hash) end def refresh_client_secret(client_identifier) - hash = call_api_service(:get, "/api/client/secret/refresh/#{client_identifier}", nil, nil) - + path = @path_resolver.refresh_client_secret(client_identifier) + hash = call_api_service(:get, path, nil, nil) Authlete::Model::Response::ClientSecretRefreshResponse.new(hash) end def update_client_secret(client_identifier, client_secret) request = Authlete::Model::Request::ClientSecretUpdateRequest.new(clientSecret: client_secret) - - hash = call_api_json_service("/api/client/secret/update/#{client_identifier}", request.to_hash) - + path = @path_resolver.update_client_secret(client_identifier) + hash = call_api_json_service(path, request.to_hash) Authlete::Model::Response::ClientSecretUpdateResponse.new(hash) end def get_client_authorization_list(request) - hash = call_api_json_service("/api/client/authorization/get/list", to_hash(request)) - + path = @path_resolver.get_client_authorization_list + hash = call_api_json_service(path, to_hash(request)) Authlete::Model::Response::AuthorizedClientListResponse.new(hash) end def update_client_authorization(client_id, request) - call_api_json_service("/api/client/authorization/update/#{client_id}", to_hash(request)) + path = @path_resolver.update_client_authorization(client_id) + call_api_json_service(path, to_hash(request)) end def delete_client_authorization(client_id, subject) request = Authlete::Model::Request::ClientAuthorizationDeleteRequest.new(subject: subject) - - call_api_json_service("/api/client/authorization/delete/#{client_id}", request.to_hash) + path = @path_resolver.delete_client_authorization(client_id) + call_api_json_service(path, request.to_hash) end def introspection(request) - hash = call_api_json_service('/api/auth/introspection', to_hash(request)) - + path = @path_resolver.introspection + hash = call_api_json_service(path, to_hash(request)) Authlete::Model::Response::IntrospectionResponse.new(hash) end def standard_introspection(request) - hash = call_api_json_service('/api/auth/introspection/standard', to_hash(request)) - + path = @path_resolver.standard_introspection + hash = call_api_json_service(path, to_hash(request)) Authlete::Model::Response::StandardIntrospectionResponse.new(hash) end def revocation(request) - hash = call_api_json_service("/api/auth/revocation", to_hash(request)) - + path = @path_resolver.revocation + hash = call_api_json_service(path, to_hash(request)) Authlete::Model::Response::RevocationResponse.new(hash) end def user_info(request) - hash = call_api_json_service("/api/auth/userinfo", to_hash(request)) - + path = @path_resolver.user_info + hash = call_api_json_service(path, to_hash(request)) Authlete::Model::Response::UserInfoResponse.new(hash) end def user_info_issue(request) - hash = call_api_json_service("/api/auth/userinfo/issue", to_hash(request)) - + path = @path_resolver.user_info_issue + hash = call_api_json_service(path, to_hash(request)) Authlete::Model::Response::UserInfoIssueResponse.new(hash) end def get_service_jwks(params = nil) - call_api_service(:get, "/api/service/jwks/get#{to_query(params)}", nil, nil) + base_path = @path_resolver.get_service_jwks + relative_path = base_path + to_query(params) + call_api_service(:get, relative_path, nil, nil) end def get_service_configuration(params = nil) - call_api_service(:get, "/api/service/configuration#{to_query(params)}", nil, nil) + base_path = @path_resolver.get_service_configuration + relative_path = base_path + to_query(params) + call_api_service(:get, relative_path, nil, nil) end def token_create(request) - hash = call_api_json_service("/api/auth/token/create", to_hash(request)) - + path = @path_resolver.token_create + hash = call_api_json_service(path, to_hash(request)) Authlete::Model::Response::TokenCreateResponse.new(hash) end def token_update(request) - hash = call_api_json_service("/api/auth/token/update", to_hash(request)) - + path = @path_resolver.token_update + hash = call_api_json_service(path, to_hash(request)) Authlete::Model::Response::TokenUpdateResponse.new(hash) end def get_token_list(params = nil) - hash = call_api_service(:get, "/api/auth/token/get/list#{to_query(params)}", nil, nil) - + base_path = @path_resolver.get_token_list + relative_path = base_path + to_query(params) + hash = call_api_service(:get, relative_path, nil, nil) Authlete::Model::Response::TokenListResponse.new(hash) end def get_granted_scopes(client_id, subject) request = Authlete::Model::Request::GrantedScopesRequest.new(subject: subject) - - hash = call_api_json_service("/api/client/granted_scopes/get/#{client_id}", to_hash(request)) - + path = @path_resolver.get_granted_scopes(client_id) + hash = call_api_json_service(path, to_hash(request)) Authlete::Model::Response::GrantedScopesGetResponse.new(hash) end def delete_granted_scopes(client_id, subject) request = Authlete::Model::Request::GrantedScopesRequest.new(subject: subject) - call_api_json_service("/api/client/granted_scopes/delete/#{client_id}", to_hash(request)) + path = @path_resolver.delete_granted_scopes(client_id) + call_api_json_service(path, to_hash(request)) end def get_requestable_scopes(client_id) - hash = call_api_service(:get, "/api/client/extension/requestable_scopes/get/#{client_id}", nil, nil) - + path = @path_resolver.get_requestable_scopes(client_id) + hash = call_api_service(:get, path, nil, nil) extract_requestable_scopes(hash) end def set_requestable_scopes(client_id, scopes) - hash = call_api_json_service("/api/client/extension/requestable_scopes/update/#{client_id}", { requestableScopes: scopes }) - + path = @path_resolver.set_requestable_scopes(client_id) + hash = call_api_json_service(path, { requestableScopes: scopes }) extract_requestable_scopes(hash) end def delete_requestable_scopes(client_id) - call_api_service(:delete, "/api/client/extension/requestable_scopes/delete/#{client_id}", nil, nil) + path = @path_resolver.delete_requestable_scopes(client_id) + call_api_service(:delete, path, nil, nil) end def dynamic_client_register(request) - hash = call_api_json_service("/api/client/registration", to_hash(request)) - + path = @path_resolver.dynamic_client_register + hash = call_api_json_service(path, to_hash(request)) Authlete::Model::Response::ClientRegistrationResponse.new(hash) end def dynamic_client_get(request) - hash = call_api_json_service("/api/client/registration/get", to_hash(request)) - + path = @path_resolver.dynamic_client_get + hash = call_api_json_service(path, to_hash(request)) Authlete::Model::Response::ClientRegistrationResponse.new(hash) end def dynamic_client_update(request) - hash = call_api_json_service("/api/client/registration/update", to_hash(request)) - + path = @path_resolver.dynamic_client_update + hash = call_api_json_service(path, to_hash(request)) Authlete::Model::Response::ClientRegistrationResponse.new(hash) end def dynamic_client_delete(request) - hash = call_api_json_service("/api/client/registration/delete", to_hash(request)) - + path = @path_resolver.dynamic_client_delete + hash = call_api_json_service(path, to_hash(request)) Authlete::Model::Response::ClientRegistrationResponse.new(hash) end def backchannel_authentication(request) - hash = call_api_json_service("/api/backchannel/authentication", to_hash(request)) - + path = @path_resolver.backchannel_authentication + hash = call_api_json_service(path, to_hash(request)) Authlete::Model::Response::BackchannelAuthenticationResponse.new(hash) end def backchannel_authentication_issue(request) - hash = call_api_json_service("/api/backchannel/authentication/issue", to_hash(request)) - + path = @path_resolver.backchannel_authentication_issue + hash = call_api_json_service(path, to_hash(request)) Authlete::Model::Response::BackchannelAuthenticationIssueResponse.new(hash) end def backchannel_authentication_fail(request) - hash = call_api_json_service("/api/backchannel/authentication/fail", to_hash(request)) - + path = @path_resolver.backchannel_authentication_fail + hash = call_api_json_service(path, to_hash(request)) Authlete::Model::Response::BackchannelAuthenticationFailResponse.new(hash) end def backchannel_authentication_complete(request) - hash = call_api_json_service("/api/backchannel/authentication/complete", to_hash(request)) - + path = @path_resolver.backchannel_authentication_complete + hash = call_api_json_service(path, to_hash(request)) Authlete::Model::Response::BackchannelAuthenticationCompleteResponse.new(hash) end def device_authorization(request) - hash = call_api_json_service("/api/device/authorization", to_hash(request)) - + path = @path_resolver.device_authorization + hash = call_api_json_service(path, to_hash(request)) Authlete::Model::Response::DeviceAuthorizationResponse.new(hash) end def device_complete(request) - hash = call_api_json_service("/api/device/complete", to_hash(request)) - + path = @path_resolver.device_complete + hash = call_api_json_service(path, to_hash(request)) Authlete::Model::Response::DeviceCompleteResponse.new(hash) end def device_verification(request) - hash = call_api_json_service("/api/device/verification", to_hash(request)) - + path = @path_resolver.device_verification + hash = call_api_json_service(path, to_hash(request)) Authlete::Model::Response::DeviceVerificationResponse.new(hash) end def push_authorization_request(request) - hash = call_api_json_service("/api/pushed_auth_req", to_hash(request)) - + path = @path_resolver.push_authorization_request + hash = call_api_json_service(path, to_hash(request)) Authlete::Model::Response::PushedAuthReqResponse.new(hash) end @@ -537,7 +615,7 @@ def protect_resource(request, scopes = nil, subject = nil) result = introspection(request) rescue => e # Error message. - message = build_error_message('/api/auth/introspection', e) + message = build_error_message(@path_resolver.introspection, e) # Emit a Rack error message. emit_rack_error_message(request, message) @@ -549,7 +627,7 @@ def protect_resource(request, scopes = nil, subject = nil) ) end - # Return the response from Authlete's /api/auth/introspection API. + # Return the response from Authlete's introspection API. result end diff --git a/lib/authlete/api_path/v2.rb b/lib/authlete/api_path/v2.rb new file mode 100644 index 0000000..b09f5d6 --- /dev/null +++ b/lib/authlete/api_path/v2.rb @@ -0,0 +1,206 @@ +module Authlete + module ApiPath + class V2 + + def authorization + "/api/auth/authorization" + end + + def authorization_issue + "/api/auth/authorization/issue" + end + + def authorization_fail + "/api/auth/authorization/fail" + end + + def token + "/api/auth/token" + end + + def token_issue + "/api/auth/token/issue" + end + + def token_fail + "/api/auth/token/fail" + end + + def token_revoke + "/api/auth/token/revoke" + end + + def service_create + "/api/service/create" + end + + def service_delete(api_key) + "/api/service/delete/#{api_key}" + end + + def service_get(api_key) + "/api/service/get/#{api_key}" + end + + def service_get_list + "/api/service/get/list" + end + + def service_update(api_key) + "/api/service/update/#{api_key}" + end + + def serviceowner_get_self + "/api/serviceowner/get/self" + end + + def client_create + "/api/client/create" + end + + def client_delete(client_id) + "/api/client/delete/#{client_id}" + end + + def client_get(client_id) + "/api/client/get/#{client_id}" + end + + def client_get_list + "/api/client/get/list" + end + + def client_update(client_id) + "/api/client/update/#{client_id}" + end + + def refresh_client_secret(client_identifier) + "/api/client/secret/refresh/#{client_identifier}" + end + + def update_client_secret(client_identifier) + "/api/client/secret/update/#{client_identifier}" + end + + def get_client_authorization_list + "/api/client/authorization/get/list" + end + + def update_client_authorization(client_id) + "/api/client/authorization/update/#{client_id}" + end + + def delete_client_authorization(client_id) + "/api/client/authorization/delete/#{client_id}" + end + + def introspection + "/api/auth/introspection" + end + + def standard_introspection + "/api/auth/introspection/standard" + end + + def revocation + "/api/auth/revocation" + end + + def user_info + "/api/auth/userinfo" + end + + def user_info_issue + "/api/auth/userinfo/issue" + end + + def get_service_jwks + "/api/service/jwks/get" + end + + def get_service_configuration + "/api/service/configuration" + end + + def token_create + "/api/auth/token/create" + end + + def token_update + "/api/auth/token/update" + end + + def get_token_list + "/api/auth/token/get/list" + end + + def get_granted_scopes(client_id) + "/api/client/granted_scopes/get/#{client_id}" + end + + def delete_granted_scopes(client_id) + "/api/client/granted_scopes/delete/#{client_id}" + end + + def get_requestable_scopes(client_id) + "/api/client/extension/requestable_scopes/get/#{client_id}" + end + + def set_requestable_scopes(client_id) + "/api/client/extension/requestable_scopes/update/#{client_id}" + end + + def delete_requestable_scopes(client_id) + "/api/client/extension/requestable_scopes/delete/#{client_id}" + end + + def dynamic_client_register + "/api/client/registration" + end + + def dynamic_client_get + "/api/client/registration/get" + end + + def dynamic_client_update + "/api/client/registration/update" + end + + def dynamic_client_delete + "/api/client/registration/delete" + end + + def backchannel_authentication + "/api/backchannel/authentication" + end + + def backchannel_authentication_issue + "/api/backchannel/authentication/issue" + end + + def backchannel_authentication_fail + "/api/backchannel/authentication/fail" + end + + def backchannel_authentication_complete + "/api/backchannel/authentication/complete" + end + + def device_authorization + "/api/device/authorization" + end + + def device_complete + "/api/device/complete" + end + + def device_verification + "/api/device/verification" + end + + def push_authorization_request + "/api/pushed_auth_req" + end + end + end +end \ No newline at end of file diff --git a/lib/authlete/api_path/v3.rb b/lib/authlete/api_path/v3.rb new file mode 100644 index 0000000..7179fe4 --- /dev/null +++ b/lib/authlete/api_path/v3.rb @@ -0,0 +1,211 @@ +module Authlete + module ApiPath + class V3 + attr_reader :service_id + + def initialize(service_id = nil) + @service_id = service_id + end + + def authorization + "/api/#{@service_id}/auth/authorization" + end + + def authorization_issue + "/api/#{@service_id}/auth/authorization/issue" + end + + def authorization_fail + "/api/#{@service_id}/auth/authorization/fail" + end + + def token + "/api/#{@service_id}/auth/token" + end + + def token_issue + "/api/#{@service_id}/auth/token/issue" + end + + def token_fail + "/api/#{@service_id}/auth/token/fail" + end + + def token_revoke + "/api/#{@service_id}/auth/token/revoke" + end + + def service_create + "/api/service/create" + end + + def service_delete(service_id) + "/api/#{service_id}/service/delete" + end + + def service_get(service_id) + "/api/#{service_id}/service/get" + end + + def service_get_list + "/api/service/get/list" + end + + def service_update(service_id) + "/api/#{service_id}/service/update" + end + + def serviceowner_get_self + raise NoMethodError, 'This API does not exist in Authlete v3.' + end + + def client_create + "/api/#{@service_id}/client/create" + end + + def client_delete(client_id) + "/api/#{@service_id}/client/delete/#{client_id}" + end + + def client_get(client_id) + "/api/#{@service_id}/client/get/#{client_id}" + end + + def client_get_list + "/api/#{@service_id}/client/get/list" + end + + def client_update(client_id) + "/api/#{@service_id}/client/update/#{client_id}" + end + + def refresh_client_secret(client_identifier) + "/api/#{@service_id}/client/secret/refresh/#{client_identifier}" + end + + def update_client_secret(client_identifier) + "/api/#{@service_id}/client/secret/update/#{client_identifier}" + end + + def get_client_authorization_list + "/api/#{@service_id}/client/authorization/get/list" + end + + def update_client_authorization(client_id) + "/api/#{@service_id}/client/authorization/update/#{client_id}" + end + + def delete_client_authorization(client_id) + "/api/#{@service_id}/client/authorization/delete/#{client_id}" + end + + def introspection + "/api/#{@service_id}/auth/introspection" + end + + def standard_introspection + "/api/#{@service_id}/auth/introspection/standard" + end + + def revocation + "/api/#{@service_id}/auth/revocation" + end + + def user_info + "/api/#{@service_id}/auth/userinfo" + end + + def user_info_issue + "/api/#{@service_id}/auth/userinfo/issue" + end + + def get_service_jwks + "/api/#{@service_id}/service/jwks/get" + end + + def get_service_configuration + "/api/#{@service_id}/service/configuration" + end + + def token_create + "/api/#{@service_id}/auth/token/create" + end + + def token_update + "/api/#{@service_id}/auth/token/update" + end + + def get_token_list + "/api/#{@service_id}/auth/token/get/list" + end + + def get_granted_scopes(client_id) + "/api/#{@service_id}/client/granted_scopes/get/#{client_id}" + end + + def delete_granted_scopes(client_id) + "/api/#{@service_id}/client/granted_scopes/delete/#{client_id}" + end + + def get_requestable_scopes(client_id) + "/api/#{@service_id}/client/extension/requestable_scopes/get/#{client_id}" + end + + def set_requestable_scopes(client_id) + "/api/#{@service_id}/client/extension/requestable_scopes/update/#{client_id}" + end + + def delete_requestable_scopes(client_id) + "/api/#{@service_id}/client/extension/requestable_scopes/delete/#{client_id}" + end + + def dynamic_client_register + "/api/#{@service_id}/client/registration" + end + + def dynamic_client_get + "/api/#{@service_id}/client/registration/get" + end + + def dynamic_client_update + "/api/#{@service_id}/client/registration/update" + end + + def dynamic_client_delete + "/api/#{@service_id}/client/registration/delete" + end + + def backchannel_authentication + "/api/#{@service_id}/backchannel/authentication" + end + + def backchannel_authentication_issue + "/api/#{@service_id}/backchannel/authentication/issue" + end + + def backchannel_authentication_fail + "/api/#{@service_id}/backchannel/authentication/fail" + end + + def backchannel_authentication_complete + "/api/#{@service_id}/backchannel/authentication/complete" + end + + def device_authorization + "/api/#{@service_id}/device/authorization" + end + + def device_complete + "/api/#{@service_id}/device/complete" + end + + def device_verification + "/api/#{@service_id}/device/verification" + end + + def push_authorization_request + "/api/#{@service_id}/pushed_auth_req" + end + end + end +end \ No newline at end of file From d972aed8b1a02a70958d199cbd1d5455404d4f5c Mon Sep 17 00:00:00 2001 From: Masakiyo Morikawa Date: Wed, 2 Apr 2025 15:22:39 +0900 Subject: [PATCH 2/2] update readme --- README.md | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 124 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 96706ac..57468c7 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,124 @@ -authlete-ruby-gem -================= - -# Overview +# authlete-ruby-gem Ruby library for [Authlete Web APIs](https://docs.authlete.com/). +## Installation + +```bash +$ gem install authlete +``` + +## Configuration + +You can configure the Authlete API client. Here are the available options: + +* `:host` (String, required): The URL of the Authlete API server (e.g., `https://api.authlete.com`). +* `:api_version` (String, optional): Specifies the Authlete API version to use. Either `'v2'` or `'v3'`. Defaults to `'v2'`. +* **For API v2:** + * `:service_owner_api_key` (String): Your service owner API key. + * `:service_owner_api_secret` (String): Your service owner API secret. + * `:service_api_key` (String): Your service API key. + * `:service_api_secret` (String): Your service API secret. +* **For API v3:** + * `:organization_access_token` (String): Your organization access token. + * `:service_access_token` (String): Your service access token. + * `:service_id` (String, required for most v3 APIs): The ID of the target service. This will be URL-encoded automatically. +* `:extra_headers` (Hash, optional): Additional HTTP headers to include in API requests. +* `:rest_client_logging_level` (Symbol, optional): Controls the logging behavior of the underlying `rest-client`. See the "REST Client Logging Configuration" section below for details. + +**Note for API v3:** Most v3 APIs require `:service_id` in the configuration. + +## Basic Usage + +Start by creating an Authlete::Api instance with your configuration. -# REST Client Logging Configuration +### API v2 Example + +```ruby +require 'authlete' + +# Configure for API v2 +config = { + host: 'https://api.authlete.com', + service_api_key: 'YOUR_SERVICE_API_KEY', + service_api_secret: 'YOUR_SERVICE_API_SECRET' + # Optionally add service_owner keys if needed + # service_owner_api_key: 'YOUR_SERVICE_OWNER_API_KEY', + # service_owner_api_secret: 'YOUR_SERVICE_OWNER_API_SECRET' +} + +api = Authlete::Api.new(config) + +# Example: Call the introspection API +begin + introspection_request = Authlete::Model::Request::IntrospectionRequest.new(token: 'ACCESS_TOKEN_TO_INTROSPECT') + response = api.introspection(introspection_request) + + if response.action == 'OK' + puts "Token is valid." + puts "Subject: #{response.subject}" + puts "Scopes: #{response.scopes.join(', ')}" + # Access other response details like response.clientId, response.expiresAt etc. + else + puts "Token introspection failed: #{response.result.resultMessage}" + # Handle other actions like 'INTERNAL_SERVER_ERROR', 'BAD_REQUEST', 'FORBIDDEN' + end +rescue Authlete::Exception => e + puts "Authlete API error: #{e.message}" + puts "Status Code: #{e.status_code}" if e.status_code + puts "Result Code: #{e.result.resultCode}" if e.result + puts "Result Message: #{e.result.resultMessage}" if e.result +end +``` + +### API v3 Example + +```ruby +require 'authlete' + +# Configure for API v3 +config = { + host: 'https://api.authlete.com', + api_version: 'v3', + service_access_token: 'YOUR_SERVICE_ACCESS_TOKEN', + service_id: 'YOUR_SERVICE_ID' # Required for most v3 APIs + # Optionally add organization token if needed + # organization_access_token: 'YOUR_ORGANIZATION_ACCESS_TOKEN' +} + +api = Authlete::Api.new(config) + +# Example: Call the introspection API +begin + introspection_request = Authlete::Model::Request::IntrospectionRequest.new(token: 'ACCESS_TOKEN_TO_INTROSPECT') + # API calls are the same, the client handles authentication based on config + response = api.introspection(introspection_request) + + if response.action == 'OK' + puts "Token is valid." + # Process response as in the v2 example + else + puts "Token introspection failed: #{response.result.resultMessage}" + # Handle errors as in the v2 example + end +rescue Authlete::Exception => e + # Handle errors as in the v2 example + puts "Authlete API error: #{e.message}" +end +``` + +## API Versioning + +This library supports both Authlete API v2 and v3. + +* **API v2 (Default):** Uses API Key and Secret pairs for authorization (`:service_api_key`, `:service_api_secret`, `:service_owner_api_key`, `:service_owner_api_secret`). +* **API v3:** Uses Bearer tokens for authorization (`:organization_access_token`, `:service_access_token`). Most v3 APIs also require a `:service_id` to be specified in the configuration. + +You can select the API version by setting the `:api_version` key in the configuration hash passed to `Authlete::Api.new`. If omitted, it defaults to `'v2'`. The `Authlete::Api` instance will automatically use the correct authorization method and API paths based on the selected version. + +--- + +## REST Client Logging Configuration The library provides control over `rest-client` logging behavior through `Authlete::LoggingLevel`: @@ -44,15 +156,18 @@ config = { api_client = Authlete::Api.new(config) ``` -# License +--- + +## License Apache License, Version 2.0 +--- -# See Also +## See Also * [Authlete Website](https://www.authlete.com/) * [Authlete Facebook](https://www.facebook.com/authlete) -* [Authelte Twitter](https://twitter.com/authlete) +* [Authlete Twitter](https://twitter.com/authlete) * [Authlete GitHub](https://github.com/authlete) -* [Authlete Email](mailto:support@authlete.com) +* [Authlete Email](mailto:support@authlete.com) \ No newline at end of file