Commit 0892b7e
Changed files (16)
app
controllers
views
oauth
authorizations
clients
spec
requests
app/controllers/oauth/clients_controller.rb
@@ -0,0 +1,54 @@
+# frozen_string_literal: true
+
+module Oauth
+ class ClientsController < ApplicationController
+ skip_before_action :authenticate!
+ before_action :apply_cache_headers
+
+ 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
+
+ private
+
+ 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
app/controllers/oauth/tokens_controller.rb
@@ -0,0 +1,111 @@
+# frozen_string_literal: true
+
+module Oauth
+ class TokensController < ApplicationController
+ def create
+ response.headers['Cache-Control'] = 'no-store'
+ response.headers['Pragma'] = 'no-cache'
+
+ @access_token, @refresh_token = tokens_for(params[:grant_type])
+ return bad_request if @access_token.nil?
+
+ render formats: :json
+ rescue StandardError => error
+ Rails.logger.error(error)
+ bad_request
+ end
+
+ def introspect
+ claims = Token.claims_for(params[:token], token_type: :any)
+ if claims.empty? || revoked_tokens[claims[:jti]]
+ render json: { active: false }, status: :ok
+ else
+ render json: claims.merge(active: true), status: :ok
+ end
+ end
+
+ def revoke
+ claims = Token.claims_for(params[:token], token_type: :any)
+ Token.find(claims[:jti]).revoke! unless claims.empty?
+ render plain: "", status: :ok
+ rescue StandardError => error
+ logger.error(error)
+ render plain: "", status: :ok
+ end
+
+ private
+
+ attr_reader :current_client
+
+ def authenticate!
+ @current_client = authenticate_with_http_basic do |client_id, client_secret|
+ Client.find(client_id)&.authenticate(client_secret)
+ end
+ return if current_client
+
+ render "invalid_client", formats: :json, status: :unauthorized
+ end
+
+ def bad_request
+ render "bad_request", formats: :json, status: :bad_request
+ end
+
+ def authorization_code_grant(
+ code = params[:code],
+ verifier = params[:code_verifier]
+ )
+ authorization = current_client.authorizations.active.find_by!(code: code)
+ return unless authorization.valid_verifier?(verifier)
+
+ authorization.issue_tokens_to(current_client)
+ end
+
+ def refresh_grant(refresh_token = params[:refresh_token])
+ jti = Token.claims_for(refresh_token, token_type: :refresh)[:jti]
+ token = Token.find(jti)
+ token.issue_tokens_to(current_client)
+ end
+
+ def password_grant(username = params[:username], password = params[:password])
+ user = User.login(username, password)
+ user.issue_tokens_to(current_client)
+ end
+
+ def assertion_grant(raw = params[:assertion])
+ assertion = Saml::Kit::Assertion.new(
+ Base64.urlsafe_decode64(raw)
+ )
+ return if assertion.invalid?
+
+ user = if assertion.name_id_format == Saml::Kit::Namespaces::PERSISTENT
+ User.find(assertion.name_id)
+ else
+ User.find_by!(email: assertion.name_id)
+ end
+ user.issue_tokens_to(current_client)
+ end
+
+ def tokens_for(grant_type = params[:grant_type])
+ case grant_type
+ when 'authorization_code'
+ authorization_code_grant
+ when 'refresh_token'
+ refresh_grant
+ when 'client_credentials'
+ [current_client.access_token, nil]
+ when 'password'
+ password_grant
+ when 'urn:ietf:params:oauth:grant-type:saml2-bearer' # RFC7522
+ assertion_grant
+ # when 'urn:ietf:params:oauth:grant-type:jwt-bearer' # RFC7523
+ # raise NotImplementedError
+ end
+ end
+
+ def revoked_tokens
+ Rails.cache.fetch("revoked-tokens", expires_in: 10.minutes) do
+ Hash[Token.revoked.pluck(:id).map { |x| [x, true] }]
+ end
+ end
+ end
+end
app/controllers/clients_controller.rb
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-
-class ClientsController < ApplicationController
- skip_before_action :authenticate!
- before_action :apply_cache_headers
-
- 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
-
- private
-
- 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
app/controllers/oauths_controller.rb
@@ -1,44 +0,0 @@
-# frozen_string_literal: true
-
-class OauthsController < ApplicationController
- VALID_RESPONSE_TYPES = %w[code token].freeze
-
- def show
- @client = Client.find(secure_params[:client_id])
-
- unless @client.valid_redirect_uri?(secure_params[:redirect_uri])
- return redirect_to @client.redirect_url(
- error: :invalid_request,
- state: secure_params[:state]
- )
- end
-
- unless @client.valid_response_type?(secure_params[:response_type])
- return redirect_to @client.redirect_url(
- error: :unsupported_response_type,
- state: secure_params[:state]
- )
- end
-
- session[:oauth] = secure_params.to_h
- end
-
- def create(oauth = session[:oauth])
- return render_error(:bad_request) if oauth.nil?
-
- client = Client.find(oauth[:client_id])
- redirect_to client.redirect_url_for(current_user, oauth)
- rescue StandardError => error
- logger.error(error)
- redirect_to client.redirect_url(error: :invalid_request)
- end
-
- private
-
- def secure_params
- params.permit(
- :client_id, :response_type, :redirect_uri,
- :state, :code_challenge, :code_challenge_method
- )
- end
-end
app/controllers/tokens_controller.rb
@@ -1,109 +0,0 @@
-# frozen_string_literal: true
-
-class TokensController < ApplicationController
- def create
- response.headers['Cache-Control'] = 'no-store'
- response.headers['Pragma'] = 'no-cache'
-
- @access_token, @refresh_token = tokens_for(params[:grant_type])
- return bad_request if @access_token.nil?
-
- render formats: :json
- rescue StandardError => error
- Rails.logger.error(error)
- bad_request
- end
-
- def introspect
- claims = Token.claims_for(params[:token], token_type: :any)
- if claims.empty? || revoked_tokens[claims[:jti]]
- render json: { active: false }, status: :ok
- else
- render json: claims.merge(active: true), status: :ok
- end
- end
-
- def revoke
- claims = Token.claims_for(params[:token], token_type: :any)
- Token.find(claims[:jti]).revoke! unless claims.empty?
- render plain: "", status: :ok
- rescue StandardError => error
- logger.error(error)
- render plain: "", status: :ok
- end
-
- private
-
- attr_reader :current_client
-
- def authenticate!
- @current_client = authenticate_with_http_basic do |client_id, client_secret|
- Client.find(client_id)&.authenticate(client_secret)
- end
- return if current_client
-
- render "invalid_client", formats: :json, status: :unauthorized
- end
-
- def bad_request
- render "bad_request", formats: :json, status: :bad_request
- end
-
- def authorization_code_grant(
- code = params[:code],
- verifier = params[:code_verifier]
- )
- authorization = current_client.authorizations.active.find_by!(code: code)
- return unless authorization.valid_verifier?(verifier)
-
- authorization.issue_tokens_to(current_client)
- end
-
- def refresh_grant(refresh_token = params[:refresh_token])
- jti = Token.claims_for(refresh_token, token_type: :refresh)[:jti]
- token = Token.find(jti)
- token.issue_tokens_to(current_client)
- end
-
- def password_grant(username = params[:username], password = params[:password])
- user = User.login(username, password)
- user.issue_tokens_to(current_client)
- end
-
- def assertion_grant(raw = params[:assertion])
- assertion = Saml::Kit::Assertion.new(
- Base64.urlsafe_decode64(raw)
- )
- return if assertion.invalid?
-
- user = if assertion.name_id_format == Saml::Kit::Namespaces::PERSISTENT
- User.find(assertion.name_id)
- else
- User.find_by!(email: assertion.name_id)
- end
- user.issue_tokens_to(current_client)
- end
-
- def tokens_for(grant_type = params[:grant_type])
- case grant_type
- when 'authorization_code'
- authorization_code_grant
- when 'refresh_token'
- refresh_grant
- when 'client_credentials'
- [current_client.access_token, nil]
- when 'password'
- password_grant
- when 'urn:ietf:params:oauth:grant-type:saml2-bearer' # RFC7522
- assertion_grant
- # when 'urn:ietf:params:oauth:grant-type:jwt-bearer' # RFC7523
- # raise NotImplementedError
- end
- end
-
- def revoked_tokens
- Rails.cache.fetch("revoked-tokens", expires_in: 10.minutes) do
- Hash[Token.revoked.pluck(:id).map { |x| [x, true] }]
- end
- end
-end
app/views/clients/create.json.jbuilder โ app/views/oauth/clients/create.json.jbuilder
File renamed without changes
app/views/tokens/bad_request.json.jbuilder โ app/views/oauth/tokens/bad_request.json.jbuilder
File renamed without changes
app/views/tokens/create.json.jbuilder โ app/views/oauth/tokens/create.json.jbuilder
File renamed without changes
app/views/tokens/invalid_client.json.jbuilder โ app/views/oauth/tokens/invalid_client.json.jbuilder
File renamed without changes
config/locales/en.yml
@@ -42,11 +42,15 @@ en:
sessions:
index:
title: Sessions
- oauths:
- show:
- authorize: Authorize
- authorize_prompt_html: Do you authorize <strong>%{name}</strong> to access your data?
- title: Authorize
+ oauth:
+ authorizations:
+ show:
+ authorize: Authorize
+ authorize_prompt_html: Do you authorize <strong>%{name}</strong> to access your data?
+ title: Authorize
+ tokens:
+ bad_request:
+ invalid_request: invalid_request
registrations:
new:
register: Register
@@ -54,6 +58,3 @@ en:
sessions:
new:
login: Login
- tokens:
- bad_request:
- invalid_request: invalid_request
config/routes.rb
@@ -5,18 +5,9 @@ Rails.application.routes.draw do
post '/oauth/token', to: 'tokens#create'
resource :mfa, only: [:new, :create]
resource :metadata, only: [:show]
- resource :oauth, only: [:show, :create] do
- get :authorize, to: "oauths#show"
- end
resource :session, only: [:new, :create, :destroy]
- resources :clients, only: [:create]
resources :registrations, only: [:new, :create]
resource :response, only: [:show]
- resource :tokens, only: [:create] do
- post :introspect
- post :revoke
- end
-
namespace :my do
resource :dashboard, only: [:show]
resource :mfa, only: [:show, :new, :edit, :create, :destroy]
@@ -24,7 +15,14 @@ Rails.application.routes.draw do
resources :clients, only: [:index, :new, :create]
resources :sessions, only: [:index]
end
-
+ namespace :oauth do
+ resource :authorizations, only: [:show, :create]
+ resources :clients, only: [:create]
+ resource :tokens, only: [:create] do
+ post :introspect
+ post :revoke
+ end
+ end
namespace :scim do
namespace :v2, defaults: { format: :scim } do
post ".search", to: "search#index"
spec/requests/clients_spec.rb โ spec/requests/oauth/clients_spec.rb
@@ -2,8 +2,8 @@
require 'rails_helper'
-RSpec.describe "/clients" do
- describe "POST /clients" do
+RSpec.describe "/oauth/clients" do
+ describe "POST /oauth/clients" do
let(:redirect_uris) { [generate(:uri), generate(:uri)] }
let(:client_name) { FFaker::Name.name }
let(:logo_uri) { generate(:uri) }
@@ -13,7 +13,7 @@ RSpec.describe "/clients" do
context "when the registration request is valid" do
before do
- post "/clients", params: {
+ post "/oauth/clients", params: {
redirect_uris: redirect_uris,
client_name: client_name,
token_endpoint_auth_method: :client_secret_basic,
@@ -40,7 +40,7 @@ RSpec.describe "/clients" do
context "when the registrations is missing valid redirect_uris" do
before do
- post "/clients", params: {
+ post "/oauth/clients", params: {
redirect_uris: [],
client_name: client_name,
token_endpoint_auth_method: :client_secret_basic,
@@ -56,7 +56,7 @@ RSpec.describe "/clients" do
context "when the registration request is missing a client name" do
before do
- post "/clients", params: {
+ post "/oauth/clients", params: {
redirect_uris: redirect_uris,
client_name: "",
token_endpoint_auth_method: :client_secret_basic,
spec/requests/tokens_spec.rb โ spec/requests/oauth/tokens_spec.rb
@@ -2,18 +2,18 @@
require 'rails_helper'
-RSpec.describe '/tokens' do
+RSpec.describe '/oauth/tokens' do
let(:client) { create(:client) }
let(:credentials) { ActionController::HttpAuthentication::Basic.encode_credentials(client.to_param, client.password) }
let(:headers) { { 'Authorization' => credentials } }
- describe "POST /oauth/token" do
+ describe "POST /oauth/tokens" do
context "when using the authorization_code grant" do
context "when the code is still valid" do
let(:authorization) { create(:authorization, client: client) }
let(:json) { JSON.parse(response.body, symbolize_names: true) }
- before { post '/oauth/token', params: { grant_type: 'authorization_code', code: authorization.code }, headers: headers }
+ before { post '/oauth/tokens', params: { grant_type: 'authorization_code', code: authorization.code }, headers: headers }
specify { expect(response).to have_http_status(:ok) }
specify { expect(response.headers['Content-Type']).to include('application/json') }
@@ -30,7 +30,7 @@ RSpec.describe '/tokens' do
let(:authorization) { create(:authorization, client: client, expired_at: 1.second.ago) }
let(:json) { JSON.parse(response.body, symbolize_names: true) }
- before { post '/oauth/token', params: { grant_type: 'authorization_code', code: authorization.code }, headers: headers }
+ before { post '/oauth/tokens', params: { grant_type: 'authorization_code', code: authorization.code }, headers: headers }
specify { expect(response).to have_http_status(:bad_request) }
specify { expect(response.headers['Content-Type']).to include('application/json') }
@@ -40,7 +40,7 @@ RSpec.describe '/tokens' do
end
context "when the code is not known" do
- before { post '/oauth/token', params: { grant_type: 'authorization_code', code: SecureRandom.hex(20) }, headers: headers }
+ before { post '/oauth/tokens', params: { grant_type: 'authorization_code', code: SecureRandom.hex(20) }, headers: headers }
let(:json) { JSON.parse(response.body, symbolize_names: true) }
@@ -58,8 +58,8 @@ RSpec.describe '/tokens' do
let(:json) { JSON.parse(response.body, symbolize_names: true) }
before do
- post '/oauth/token', params: { grant_type: 'authorization_code', code: SecureRandom.hex(20) }, headers: headers
- post '/oauth/token', params: { grant_type: 'authorization_code', code: authorization.code, code_verifier: code_verifier }, headers: headers
+ post '/oauth/tokens', params: { grant_type: 'authorization_code', code: SecureRandom.hex(20) }, headers: headers
+ post '/oauth/tokens', params: { grant_type: 'authorization_code', code: authorization.code, code_verifier: code_verifier }, headers: headers
end
specify { expect(response).to have_http_status(:ok) }
@@ -79,8 +79,8 @@ RSpec.describe '/tokens' do
let(:json) { JSON.parse(response.body, symbolize_names: true) }
before do
- post '/oauth/token', params: { grant_type: 'authorization_code', code: SecureRandom.hex(20) }, headers: headers
- post '/oauth/token', params: { grant_type: 'authorization_code', code: authorization.code, code_verifier: code_verifier }, headers: headers
+ post '/oauth/tokens', params: { grant_type: 'authorization_code', code: SecureRandom.hex(20) }, headers: headers
+ post '/oauth/tokens', params: { grant_type: 'authorization_code', code: authorization.code, code_verifier: code_verifier }, headers: headers
end
specify { expect(response).to have_http_status(:ok) }
@@ -100,8 +100,8 @@ RSpec.describe '/tokens' do
let(:json) { JSON.parse(response.body, symbolize_names: true) }
before do
- post '/oauth/token', params: { grant_type: 'authorization_code', code: SecureRandom.hex(20) }, headers: headers
- post '/oauth/token', params: { grant_type: 'authorization_code', code: authorization.code, code_verifier: 'invalid' }, headers: headers
+ post '/oauth/tokens', params: { grant_type: 'authorization_code', code: SecureRandom.hex(20) }, headers: headers
+ post '/oauth/tokens', params: { grant_type: 'authorization_code', code: authorization.code, code_verifier: 'invalid' }, headers: headers
end
specify { expect(response).to have_http_status(:bad_request) }
@@ -118,8 +118,8 @@ RSpec.describe '/tokens' do
let(:json) { JSON.parse(response.body, symbolize_names: true) }
before do
- post '/oauth/token', params: { grant_type: 'authorization_code', code: SecureRandom.hex(20) }, headers: headers
- post '/oauth/token', params: { grant_type: 'authorization_code', code: authorization.code, code_verifier: 'invalid' }, headers: headers
+ post '/oauth/tokens', params: { grant_type: 'authorization_code', code: SecureRandom.hex(20) }, headers: headers
+ post '/oauth/tokens', params: { grant_type: 'authorization_code', code: authorization.code, code_verifier: 'invalid' }, headers: headers
end
specify { expect(response).to have_http_status(:bad_request) }
@@ -135,7 +135,7 @@ RSpec.describe '/tokens' do
context "when the client credentials are valid" do
let(:json) { JSON.parse(response.body, symbolize_names: true) }
- before { post '/oauth/token', params: { grant_type: 'client_credentials' }, headers: headers }
+ before { post '/oauth/tokens', params: { grant_type: 'client_credentials' }, headers: headers }
specify { expect(response).to have_http_status(:ok) }
specify { expect(response.headers['Content-Type']).to include('application/json') }
@@ -151,7 +151,7 @@ RSpec.describe '/tokens' do
let(:headers) { { 'Authorization' => 'invalid' } }
let(:json) { JSON.parse(response.body, symbolize_names: true) }
- before { post '/oauth/token', params: { grant_type: 'client_credentials' }, headers: headers }
+ before { post '/oauth/tokens', params: { grant_type: 'client_credentials' }, headers: headers }
specify { expect(response).to have_http_status(:unauthorized) }
specify { expect(json[:error]).to eql('invalid_client') }
@@ -163,7 +163,7 @@ RSpec.describe '/tokens' do
let(:user) { create(:user) }
let(:json) { JSON.parse(response.body, symbolize_names: true) }
- before { post '/oauth/token', params: { grant_type: 'password', username: user.email, password: user.password }, headers: headers }
+ before { post '/oauth/tokens', params: { grant_type: 'password', username: user.email, password: user.password }, headers: headers }
specify { expect(response).to have_http_status(:ok) }
specify { expect(response.headers['Content-Type']).to include('application/json') }
@@ -178,7 +178,7 @@ RSpec.describe '/tokens' do
context "when the credentials are invalid" do
let(:json) { JSON.parse(response.body, symbolize_names: true) }
- before { post '/oauth/token', params: { grant_type: 'password', username: generate(:email), password: generate(:password) }, headers: headers }
+ before { post '/oauth/tokens', params: { grant_type: 'password', username: generate(:email), password: generate(:password) }, headers: headers }
specify { expect(response).to have_http_status(:bad_request) }
specify { expect(json[:error]).to eql('invalid_request') }
@@ -190,7 +190,7 @@ RSpec.describe '/tokens' do
let(:refresh_token) { create(:refresh_token) }
let(:json) { JSON.parse(response.body, symbolize_names: true) }
- before { post '/oauth/token', params: { grant_type: 'refresh_token', refresh_token: refresh_token.to_jwt }, headers: headers }
+ before { post '/oauth/tokens', params: { grant_type: 'refresh_token', refresh_token: refresh_token.to_jwt }, headers: headers }
specify { expect(response).to have_http_status(:ok) }
specify { expect(response.headers['Content-Type']).to include('application/json') }
@@ -214,7 +214,7 @@ RSpec.describe '/tokens' do
before do
allow(Saml::Kit.configuration.registry).to receive(:metadata_for).and_return(metadata)
- post '/oauth/token', params: {
+ post '/oauth/tokens', params: {
grant_type: 'urn:ietf:params:oauth:grant-type:saml2-bearer',
assertion: Base64.urlsafe_encode64(saml),
}, headers: headers
@@ -239,7 +239,7 @@ RSpec.describe '/tokens' do
before do
allow(Saml::Kit.configuration.registry).to receive(:metadata_for).and_return(metadata)
- post '/oauth/token', params: {
+ post '/oauth/tokens', params: {
grant_type: 'urn:ietf:params:oauth:grant-type:saml2-bearer',
assertion: Base64.urlsafe_encode64(saml),
}, headers: headers
@@ -265,7 +265,7 @@ RSpec.describe '/tokens' do
before do
allow(Saml::Kit.configuration.registry).to receive(:metadata_for).and_return(metadata)
- post '/oauth/token', params: {
+ post '/oauth/tokens', params: {
grant_type: 'urn:ietf:params:oauth:grant-type:saml2-bearer',
assertion: Base64.urlsafe_encode64(saml),
}, headers: headers
@@ -288,7 +288,7 @@ RSpec.describe '/tokens' do
before do
allow(Saml::Kit.configuration.registry).to receive(:metadata_for).and_return(metadata)
- post '/oauth/token', params: {
+ post '/oauth/tokens', params: {
grant_type: 'urn:ietf:params:oauth:grant-type:saml2-bearer',
assertion: Base64.urlsafe_encode64(saml),
}, headers: headers
@@ -303,12 +303,12 @@ RSpec.describe '/tokens' do
end
end
- describe "POST /tokens/introspect" do
+ describe "POST /oauth/tokens/introspect" do
context "when the access_token is valid" do
let(:token) { create(:access_token) }
let(:json) { JSON.parse(response.body, symbolize_names: true) }
- before { post '/tokens/introspect', params: { token: token.to_jwt }, headers: headers }
+ before { post '/oauth/tokens/introspect', params: { token: token.to_jwt }, headers: headers }
specify { expect(response).to have_http_status(:ok) }
specify { expect(response['Content-Type']).to include('application/json') }
@@ -324,7 +324,7 @@ RSpec.describe '/tokens' do
let(:token) { create(:refresh_token) }
let(:json) { JSON.parse(response.body, symbolize_names: true) }
- before { post '/tokens/introspect', params: { token: token.to_jwt }, headers: headers }
+ before { post '/oauth/tokens/introspect', params: { token: token.to_jwt }, headers: headers }
specify { expect(response).to have_http_status(:ok) }
specify { expect(response['Content-Type']).to include('application/json') }
@@ -340,7 +340,7 @@ RSpec.describe '/tokens' do
let(:token) { create(:access_token, :revoked) }
let(:json) { JSON.parse(response.body, symbolize_names: true) }
- before { post '/tokens/introspect', params: { token: token.to_jwt }, headers: headers }
+ before { post '/oauth/tokens/introspect', params: { token: token.to_jwt }, headers: headers }
specify { expect(response).to have_http_status(:ok) }
specify { expect(response['Content-Type']).to include('application/json') }
@@ -351,7 +351,7 @@ RSpec.describe '/tokens' do
let(:token) { create(:access_token, :expired) }
let(:json) { JSON.parse(response.body, symbolize_names: true) }
- before { post '/tokens/introspect', params: { token: token.to_jwt }, headers: headers }
+ before { post '/oauth/tokens/introspect', params: { token: token.to_jwt }, headers: headers }
specify { expect(response).to have_http_status(:ok) }
specify { expect(response['Content-Type']).to include('application/json') }
@@ -359,12 +359,12 @@ RSpec.describe '/tokens' do
end
end
- describe "POST /tokens/revoke" do
+ describe "POST /oauth/tokens/revoke" do
context "when the client credentials are valid" do
context "when the access token is active and known" do
let(:token) { create(:access_token) }
- before { post '/tokens/revoke', params: { token: token.to_jwt, token_type_hint: :access_token }, headers: headers }
+ before { post '/oauth/tokens/revoke', params: { token: token.to_jwt, token_type_hint: :access_token }, headers: headers }
specify { expect(response).to have_http_status(:ok) }
specify { expect(response.body).to be_empty }
@@ -374,7 +374,7 @@ RSpec.describe '/tokens' do
context "when the refresh token is active and known" do
let(:token) { create(:refresh_token) }
- before { post '/tokens/revoke', params: { token: token.to_jwt, token_type_hint: :refresh_token }, headers: headers }
+ before { post '/oauth/tokens/revoke', params: { token: token.to_jwt, token_type_hint: :refresh_token }, headers: headers }
specify { expect(response).to have_http_status(:ok) }
specify { expect(response.body).to be_empty }
@@ -384,7 +384,7 @@ RSpec.describe '/tokens' do
context "when the access token is expired" do
let(:token) { create(:access_token, :expired) }
- before { post '/tokens/revoke', params: { token: token.to_jwt, token_type_hint: :refresh_token }, headers: headers }
+ before { post '/oauth/tokens/revoke', params: { token: token.to_jwt, token_type_hint: :refresh_token }, headers: headers }
specify { expect(response).to have_http_status(:ok) }
end