Commit af35858
Changed files (4)
app
spec
requests
app/controllers/oauths_controller.rb
@@ -2,17 +2,36 @@
class OauthsController < ApplicationController
def show
- return render_error(:not_found) unless params[:response_type] == 'code'
+ return render_error(:not_found) unless params[:response_type] == 'code' || params[:response_type] == 'token'
@client = Client.find_by!(uuid: params[:client_id])
+ session[:oauth] = {
+ client_id: params[:client_id],
+ response_type: params[:response_type],
+ state: params[:state],
+ }
+
end
def create
- client = Client.find_by!(uuid: params[:client_id])
+ client = Client.find_by!(uuid: session[:oauth][:client_id])
authorization = client.authorizations.create!(user: current_user)
- redirect_to client.redirect_uri_path(
- code: authorization.code,
- state: params[:state]
- )
+
+ if 'code' == session[:oauth][:response_type]
+ redirect_to client.redirect_uri_path(
+ code: authorization.code,
+ state: session[:oauth][:state]
+ )
+ elsif 'token' == session[:oauth][:response_type]
+ @access_token, _ = authorization.issue_tokens_to(client)
+
+ redirect_to client.redirect_uri_path(
+ access_token: @access_token.to_jwt,
+ token_type: "Bearer",
+ expires_in: 5.minutes,
+ scope: "admin",
+ state: session[:oauth][:state]
+ )
+ end
end
end
app/models/client.rb
@@ -27,8 +27,16 @@ class Client < ApplicationRecord
uuid
end
- def redirect_uri_path(code:, state: nil)
- result = redirect_uri + '?code=' + code
+ def redirect_uri_path(code: nil, access_token: nil, token_type: "Bearer", expires_in: nil, scope: "", state: nil)
+ result = redirect_uri
+ if code
+ result += '?code=' + code
+ elsif access_token
+ result += '#access_token=' + access_token
+ result += "&token_type=#{token_type}"
+ result += "&expires_in=#{expires_in.seconds.to_i}" if expires_in.present?
+ result += "&scope=#{scope}" if scope.present?
+ end
result += "&state=#{state}" if state.present?
result
end
app/views/oauths/show.html.erb
@@ -4,8 +4,6 @@
<h1><%= t('.title') %></h1>
<p><%= t('.authorize_prompt_html', name: @client.name) %></p>
<%= form_for :authorization, url: oauth_path, method: :post do |form| %>
- <%= hidden_field_tag :client_id, @client.to_param %>
- <%= hidden_field_tag :state, params[:state] %>
<%= form.button t('.authorize'), type: 'submit', class: 'btn btn-primary', data: { disable_with: t('loading') } %>
<% end %>
</div>
spec/requests/oauth_spec.rb
@@ -12,11 +12,16 @@ RSpec.describe '/oauth' do
context "when the client id is known" do
let(:client) { create(:client) }
- context "when the correct parameters are provided" do
+ context "when requesting an authorization code" do
before { get "/oauth", params: { client_id: client.to_param, response_type: 'code', state: state } }
specify { expect(response).to have_http_status(:ok) }
specify { expect(response.body).to include(CGI.escapeHTML(client.name)) }
- specify { expect(response.body).to include(state) }
+ end
+
+ context "when requesting an access token" do
+ before { get "/oauth", params: { client_id: client.to_param, response_type: 'token', state: state } }
+ specify { expect(response).to have_http_status(:ok) }
+ specify { expect(response.body).to include(CGI.escapeHTML(client.name)) }
end
context "when an incorrect response_type is provided" do
@@ -36,7 +41,6 @@ RSpec.describe '/oauth' do
specify { expect(response).to have_http_status(:ok) }
specify { expect(response.body).to include(CGI.escapeHTML(client.name)) }
- specify { expect(response.body).to include(state) }
end
end
@@ -45,9 +49,29 @@ RSpec.describe '/oauth' do
let(:client) { create(:client) }
let(:state) { SecureRandom.uuid }
- before { post "/oauth", params: { client_id: client.to_param, state: state } }
+ context "when the client requested an authorization code" do
+ before :each do
+ get "/oauth", params: { client_id: client.to_param, response_type: 'code', state: state }
+ post "/oauth"
+ end
- specify { expect(response).to redirect_to(client.redirect_uri_path(code: Authorization.last.code, state: state)) }
+ specify { expect(response).to redirect_to(client.redirect_uri_path(code: Authorization.last.code, state: state)) }
+ end
+
+ context "when the client requested a token" do
+ let(:token) { Token.access.active.last&.to_jwt }
+ let(:scope) { "admin" }
+
+ before :each do
+ get "/oauth", params: { client_id: client.to_param, response_type: 'token', state: state }
+ post "/oauth"
+ end
+
+ specify do
+ expected_url = "#{client.redirect_uri}#access_token=#{token}&token_type=Bearer&expires_in=300&scope=#{scope}&state=#{state}"
+ expect(response).to redirect_to(expected_url)
+ end
+ end
end
end
end