main
1# frozen_string_literal: true
2
3module Oauth
4 class ClientsController < ActionController::API
5 include ActionController::HttpAuthentication::Token::ControllerMethods
6 before_action :apply_cache_headers
7 before_action :authenticate!, except: [:create]
8
9 def show
10 render status: :ok, formats: :json
11 end
12
13 def create
14 @client = Client.create!(transform(secure_params))
15 render status: :created, formats: :json
16 rescue ActiveRecord::RecordInvalid => error
17 json = {
18 error: error_type_for(error.record.errors),
19 error_description: error.record.errors.full_messages.join(' ')
20 }
21 render json: json, status: :bad_request
22 end
23
24 def update
25 @client = Client.find(params[:id])
26 @client.update!(transform(secure_params))
27 render status: :ok, formats: :json
28 rescue ActiveRecord::RecordInvalid => error
29 json = {
30 error: error_type_for(error.record.errors),
31 error_description: error.record.errors.full_messages.join(' ')
32 }
33 render json: json, status: :bad_request
34 end
35
36 private
37
38 def authenticate!
39 token = authenticate_with_http_token do |jwt, _options|
40 claims = Token.claims_for(jwt)
41 return if Token.revoked?(claims[:jti]) || claims.empty?
42
43 Token.find(claims[:jti])
44 end
45 return request_http_token_authentication if token.blank?
46
47 unless Client.where(id: params[:id]).exists?
48 token.revoke!
49 return render json: {}, status: :unauthorized
50 end
51 unless token.subject.to_param == params[:id]
52 return render json: {}, status: :forbidden
53 end
54
55 @client = token.subject
56 end
57
58 def secure_params
59 params.permit(
60 :client_name,
61 :token_endpoint_auth_method,
62 :logo_uri,
63 :jwks_uri,
64 redirect_uris: []
65 )
66 end
67
68 def transform(params)
69 {
70 name: params[:client_name],
71 redirect_uris: params[:redirect_uris],
72 token_endpoint_auth_method: params[:token_endpoint_auth_method],
73 logo_uri: params[:logo_uri],
74 jwks_uri: params[:jwks_uri],
75 }
76 end
77
78 def apply_cache_headers
79 response.headers["Cache-Control"] = "no-cache, no-store"
80 response.headers["Pragma"] = "no-cache"
81 end
82
83 def error_type_for(errors)
84 if errors[:redirect_uris].present?
85 :invalid_redirect_uri
86 else
87 :invalid_client_metadata
88 end
89 end
90 end
91end