summaryrefslogtreecommitdiff
path: root/app/controllers/oauth/clients_controller.rb
blob: fa107f91a6c068fec93abeb7d3ecfe7a08072659 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# frozen_string_literal: true

module Oauth
  class ClientsController < ActionController::API
    include ActionController::HttpAuthentication::Token::ControllerMethods
    before_action :apply_cache_headers
    before_action :authenticate!, except: [:create]

    def show
      render status: :ok, formats: :json
    end

    def create
      @client = Client.create!(transform(secure_params))
      render status: :created, formats: :json
    rescue ActiveRecord::RecordInvalid => error
      json = {
        error: error_type_for(error.record.errors),
        error_description: error.record.errors.full_messages.join(' ')
      }
      render json: json, status: :bad_request
    end

    def update
      @client = Client.find(params[:id])
      @client.update!(transform(secure_params))
      render status: :ok, formats: :json
    rescue ActiveRecord::RecordInvalid => error
      json = {
        error: error_type_for(error.record.errors),
        error_description: error.record.errors.full_messages.join(' ')
      }
      render json: json, status: :bad_request
    end

    private

    def authenticate!
      token = authenticate_with_http_token do |jwt, _options|
        claims = Token.claims_for(jwt)
        return if Token.revoked?(claims[:jti]) || claims.empty?

        Token.find(claims[:jti])
      end
      return request_http_token_authentication if token.blank?

      unless Client.where(id: params[:id]).exists?
        token.revoke!
        return render json: {}, status: :unauthorized
      end
      unless token.subject.to_param == params[:id]
        return render json: {}, status: :forbidden
      end

      @client = token.subject
    end

    def secure_params
      params.permit(
        :client_name,
        :token_endpoint_auth_method,
        :logo_uri,
        :jwks_uri,
        redirect_uris: []
      )
    end

    def transform(params)
      {
        name: params[:client_name],
        redirect_uris: params[:redirect_uris],
        token_endpoint_auth_method: params[:token_endpoint_auth_method],
        logo_uri: params[:logo_uri],
        jwks_uri: params[:jwks_uri],
      }
    end

    def apply_cache_headers
      response.headers["Cache-Control"] = "no-cache, no-store"
      response.headers["Pragma"] = "no-cache"
    end

    def error_type_for(errors)
      if errors[:redirect_uris].present?
        :invalid_redirect_uri
      else
        :invalid_client_metadata
      end
    end
  end
end