module Doorkeeper
  module OpenidConnect
    class DiscoveryController < ::Doorkeeper::ApplicationController
      include Doorkeeper::Helpers::Controller

      WEBFINGER_RELATION = 'http://openid.net/specs/connect/1.0/issuer'.freeze

      def provider
        render json: provider_response
      end

      def webfinger
        render json: webfinger_response
      end

      def keys
        render json: keys_response
      end

      private

      def provider_response
        doorkeeper = ::Doorkeeper.configuration
        openid_connect = ::Doorkeeper::OpenidConnect.configuration
        {
          issuer: openid_connect.issuer,
          authorization_endpoint: oauth_authorization_url(protocol: protocol),
          token_endpoint: oauth_token_url(protocol: protocol),
          userinfo_endpoint: oauth_userinfo_url(protocol: protocol),
          jwks_uri: oauth_discovery_keys_url(protocol: protocol),

          scopes_supported: doorkeeper.scopes,

          # TODO: support id_token response type
          response_types_supported: doorkeeper.authorization_response_types,
          response_modes_supported: [ 'query', 'fragment', 'form_post' ],

          token_endpoint_auth_methods_supported: [
            'client_secret_basic',
            'client_secret_post',

            # TODO: look into doorkeeper-jwt_assertion for these
            #'client_secret_jwt',
            #'private_key_jwt'
          ],

          subject_types_supported: openid_connect.subject_types_supported,

          id_token_signing_alg_values_supported: [
            ::Doorkeeper::OpenidConnect.signing_algorithm
          ],

          claim_types_supported: [
            'normal',

            # TODO: support these
            #'aggregated',
            #'distributed',
          ],

          claims_supported: [
            'iss',
            'sub',
            'aud',
            'exp',
            'iat',
          ] | openid_connect.claims.to_h.keys,
        }
      end

      def webfinger_response
        {
          subject: params.require(:resource),
          links: [
            {
              rel: WEBFINGER_RELATION,
              href: root_url(protocol: protocol),
            }
          ]
        }
      end

      def keys_response
        signing_key = Doorkeeper::OpenidConnect.signing_key_normalized

        {
          keys: [
            signing_key.merge(
              use: 'sig',
              alg: Doorkeeper::OpenidConnect.signing_algorithm
            )
          ]
        }
      end

      def protocol
        Doorkeeper::OpenidConnect.configuration.protocol.call
      end
    end
  end
end
