Add support for access tokens in implicit flow
Squashed commits: [7dbf618] Use Rail's find_or_create_by method
This commit is contained in:
parent
2d762da072
commit
ee9ac06e1a
6 changed files with 73 additions and 43 deletions
|
|
@ -76,7 +76,7 @@ class OpenidConnect::AuthorizationsController < ApplicationController
|
|||
req = Rack::Request.new(request.env)
|
||||
req.update_param("client_id", session[:client_id])
|
||||
req.update_param("redirect_uri", session[:redirect_uri])
|
||||
req.update_param("response_type", session[:response_type])
|
||||
req.update_param("response_type", session[:response_type].respond_to?(:map) ? session[:response_type].map(&:to_s).join(" ") : session[:response_type])
|
||||
req.update_param("scopes", session[:scopes])
|
||||
req.update_param("request_object", session[:request_object])
|
||||
req.update_param("nonce", session[:nonce])
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@ class OpenidConnect::Authorization < ActiveRecord::Base
|
|||
belongs_to :user
|
||||
belongs_to :o_auth_application
|
||||
|
||||
validates :user, presence: true, uniqueness: true
|
||||
validates :o_auth_application, presence: true, uniqueness: true
|
||||
validates :user, presence: true
|
||||
validates :o_auth_application, presence: true
|
||||
|
||||
has_many :scopes, through: :authorization_scopes
|
||||
has_many :o_auth_access_tokens, dependent: :destroy
|
||||
has_many :id_tokens
|
||||
has_many :id_tokens, dependent: :destroy
|
||||
|
||||
def generate_refresh_token
|
||||
self.refresh_token = SecureRandom.hex(32)
|
||||
|
|
@ -15,6 +15,11 @@ class OpenidConnect::Authorization < ActiveRecord::Base
|
|||
|
||||
def create_access_token
|
||||
o_auth_access_tokens.create!.bearer_token
|
||||
# TODO: Add support for request object
|
||||
end
|
||||
|
||||
def create_id_token(nonce)
|
||||
id_tokens.create!(nonce: nonce)
|
||||
end
|
||||
|
||||
def self.find_by_client_id_and_user(client_id, user)
|
||||
|
|
@ -22,15 +27,5 @@ class OpenidConnect::Authorization < ActiveRecord::Base
|
|||
find_by(o_auth_application: app, user: user)
|
||||
end
|
||||
|
||||
def self.find_by_app_and_user(app, user)
|
||||
find_by(o_auth_application: app, user: user)
|
||||
end
|
||||
|
||||
# TODO: Handle creation error
|
||||
def self.find_or_create(client_id, user)
|
||||
app = OpenidConnect::OAuthApplication.find_by(client_id: client_id)
|
||||
find_by_app_and_user(app, user) || create!(user: user, o_auth_application: app)
|
||||
end
|
||||
|
||||
# TODO: Consider splitting into subclasses by flow type
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ class OpenidConnect::OAuthAccessToken < ActiveRecord::Base
|
|||
before_validation :setup, on: :create
|
||||
|
||||
validates :token, presence: true, uniqueness: true
|
||||
validates :authorization, presence: true, uniqueness: true
|
||||
validates :authorization, presence: true
|
||||
|
||||
scope :valid, ->(time) { where("expires_at >= ?", time) }
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ class OpenidConnect::OAuthApplication < ActiveRecord::Base
|
|||
|
||||
class << self
|
||||
def available_response_types
|
||||
["id_token"]
|
||||
["id_token", "id_token token"]
|
||||
end
|
||||
|
||||
def register!(registrar)
|
||||
|
|
|
|||
|
|
@ -18,14 +18,17 @@ module OpenidConnect
|
|||
end
|
||||
end
|
||||
|
||||
# TODO: Add support for request object and auth code
|
||||
def approved!(req, res)
|
||||
auth = OpenidConnect::Authorization.find_or_create(req.client_id, @user)
|
||||
auth = OpenidConnect::Authorization.find_or_create_by(o_auth_application: @o_auth_application, user: @user)
|
||||
response_types = Array(req.response_type)
|
||||
if response_types.include?(:token)
|
||||
res.access_token = auth.create_access_token
|
||||
end
|
||||
if response_types.include?(:id_token)
|
||||
id_token = auth.id_tokens.create!(nonce: req.nonce)
|
||||
options = %i(code access_token).map{|option| ["res.#{option}", res.respond_to?(option) ? res.option : nil]}.to_h
|
||||
res.id_token = id_token.to_jwt(options)
|
||||
# TODO: Add support for request object
|
||||
id_token = auth.create_id_token(req.nonce)
|
||||
access_token_value = res.respond_to?(:access_token) ? res.access_token : nil
|
||||
res.id_token = id_token.to_jwt(code: nil, access_token: access_token_value)
|
||||
end
|
||||
res.approve!
|
||||
end
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ describe OpenidConnect::AuthorizationsController, type: :controller do
|
|||
end
|
||||
end
|
||||
context "when already authorized" do
|
||||
let!(:auth) { OpenidConnect::Authorization.find_or_create(client.client_id, alice) }
|
||||
let!(:auth) { OpenidConnect::Authorization.find_or_create_by(o_auth_application: client, user: alice) }
|
||||
|
||||
context "when valid parameters are passed" do
|
||||
before do
|
||||
|
|
@ -113,6 +113,36 @@ describe OpenidConnect::AuthorizationsController, type: :controller do
|
|||
end
|
||||
|
||||
describe "#create" do
|
||||
|
||||
context "when id_token token" do
|
||||
before do
|
||||
get :new, client_id: client.client_id, redirect_uri: "http://localhost:3000/", response_type: "id_token token",
|
||||
scope: "openid", nonce: 418_093_098_3, state: 418_093_098_3
|
||||
end
|
||||
|
||||
context "when authorization is approved" do
|
||||
before do
|
||||
post :create, approve: "true"
|
||||
end
|
||||
|
||||
it "should return the id token in a fragment" do
|
||||
encoded_id_token = response.location[/(?<=id_token=)[^&]+/]
|
||||
decoded_token = OpenIDConnect::ResponseObject::IdToken.decode encoded_id_token, OpenidConnect::IdTokenConfig.public_key
|
||||
expect(decoded_token.nonce).to eq("4180930983")
|
||||
expect(decoded_token.exp).to be > Time.now.utc.to_i
|
||||
end
|
||||
|
||||
it "should return a valid access token in a fragment" do
|
||||
encoded_id_token = response.location[/(?<=id_token=)[^&]+/]
|
||||
decoded_token = OpenIDConnect::ResponseObject::IdToken.decode encoded_id_token, OpenidConnect::IdTokenConfig.public_key
|
||||
access_token = response.location[/(?<=access_token=)[^&]+/]
|
||||
access_token_check_num = UrlSafeBase64.encode64(OpenSSL::Digest::SHA256.digest(access_token)[0, 128 / 8])
|
||||
expect(decoded_token.at_hash).to eq(access_token_check_num)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "when id_token" do
|
||||
before do
|
||||
get :new, client_id: client.client_id, redirect_uri: "http://localhost:3000/", response_type: "id_token",
|
||||
scope: "openid", nonce: 418_093_098_3, state: 418_093_098_3
|
||||
|
|
@ -150,4 +180,6 @@ describe OpenidConnect::AuthorizationsController, type: :controller do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in a new issue