Fix authorization and related models
Squashed commits: [a844d37] Remove unnecessary class_name's from models [529a30c] Further adjust authorization and related models
This commit is contained in:
parent
031679762a
commit
1475672d72
14 changed files with 46 additions and 52 deletions
|
|
@ -2,4 +2,8 @@ class Api::V0::BaseController < ApplicationController
|
||||||
include OpenidConnect::ProtectedResourceEndpoint
|
include OpenidConnect::ProtectedResourceEndpoint
|
||||||
|
|
||||||
before_filter :require_access_token
|
before_filter :require_access_token
|
||||||
|
|
||||||
|
def authorization
|
||||||
|
current_token.authorization
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,6 @@ class Api::V0::UsersController < Api::V0::BaseController
|
||||||
private
|
private
|
||||||
|
|
||||||
def user
|
def user
|
||||||
current_token.user
|
authorization.user
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,43 +1,38 @@
|
||||||
class OpenidConnect::Authorization < ActiveRecord::Base
|
class OpenidConnect::Authorization < ActiveRecord::Base
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
belongs_to :o_auth_application
|
belongs_to :o_auth_application
|
||||||
|
|
||||||
has_many :scopes, through: :authorization_scopes
|
has_many :scopes, through: :authorization_scopes
|
||||||
has_many :o_auth_access_tokens
|
has_many :o_auth_access_tokens
|
||||||
|
|
||||||
before_validation :setup, on: :create
|
before_validation :setup, on: :create
|
||||||
|
|
||||||
validates :refresh_token, uniqueness: true
|
validates :refresh_token, presence: true, uniqueness: true
|
||||||
validates :user, :o_auth_application, uniqueness: true
|
validates :user, presence: true, uniqueness: true
|
||||||
|
validates :o_auth_application, presence: true, uniqueness: true
|
||||||
# TODO: Incomplete class
|
|
||||||
|
|
||||||
def setup
|
def setup
|
||||||
self.refresh_token = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.valid?(token)
|
|
||||||
OpenidConnect::Authorization.exists? refresh_token: token
|
|
||||||
end
|
|
||||||
|
|
||||||
def create_refresh_token
|
|
||||||
self.refresh_token = SecureRandom.hex(32)
|
self.refresh_token = SecureRandom.hex(32)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_token
|
def create_access_token
|
||||||
o_auth_access_tokens.create!.bearer_token
|
OpenidConnect::OAuthAccessToken.create!(authorization: self).bearer_token
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.find_by_client_id_and_user(client_id, user)
|
# TODO: Actually call this method from token endpoint
|
||||||
app = OpenidConnect::OAuthApplication.find_by(client_id: client_id)
|
def regenerate_refresh_token
|
||||||
|
self.refresh_token = SecureRandom.hex(32)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.find_by_client_id_and_user(app, user)
|
||||||
find_by(o_auth_application: app, user: user)
|
find_by(o_auth_application: app, user: user)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.find_or_create(client_id, user)
|
|
||||||
auth = find_by_client_id_and_user client_id, user
|
|
||||||
unless auth
|
|
||||||
# TODO: Handle creation error
|
# TODO: Handle creation error
|
||||||
auth = create! user: user, o_auth_application: OpenidConnect::OAuthApplication.find_by(client_id: client_id)
|
def self.find_or_create(client_id, user)
|
||||||
end
|
app = OpenidConnect::OAuthApplication.find_by(client_id: client_id)
|
||||||
auth
|
find_by_client_id_and_user(app, user) || create!(user: user, o_auth_application: app)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# TODO: Incomplete class
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
class AuthorizationScope < ActiveRecord::Base
|
class OpenidConnect::AuthorizationScope < ActiveRecord::Base
|
||||||
belongs_to authorization
|
belongs_to :authorization
|
||||||
belongs_to scope
|
belongs_to :scope
|
||||||
|
|
||||||
validates authorization, presence: true
|
validates :authorization, presence: true
|
||||||
validates scope, presence: true
|
validates :scope, presence: true
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
class OpenidConnect::OAuthAccessToken < ActiveRecord::Base
|
class OpenidConnect::OAuthAccessToken < ActiveRecord::Base
|
||||||
belongs_to :user
|
belongs_to :authorization, dependent: :delete
|
||||||
belongs_to :authorization
|
|
||||||
has_many :scopes, through: :scope_tokens
|
has_many :scopes, through: :scope_tokens
|
||||||
|
|
||||||
before_validation :setup, on: :create
|
before_validation :setup, on: :create
|
||||||
|
|
||||||
validates :token, presence: true, uniqueness: true
|
validates :token, presence: true, uniqueness: true
|
||||||
|
validates :authorization, presence: true, uniqueness: true
|
||||||
|
|
||||||
scope :valid, ->(time) { where("expires_at >= ?", time) }
|
scope :valid, ->(time) { where("expires_at >= ?", time) }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
class OpenidConnect::OAuthApplication < ActiveRecord::Base
|
class OpenidConnect::OAuthApplication < ActiveRecord::Base
|
||||||
belongs_to :user
|
|
||||||
|
|
||||||
has_many :authorizations
|
has_many :authorizations
|
||||||
has_many :user, through: :authorizations
|
has_many :user, through: :authorizations
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
class OpenidConnect::Scope < ActiveRecord::Base
|
class OpenidConnect::Scope < ActiveRecord::Base
|
||||||
has_many :tokens, through: :scope_tokens
|
has_many :o_auth_access_token, through: :scope_tokens
|
||||||
has_many :authorizations, through: :authorization_scopes
|
has_many :authorizations, through: :authorization_scopes
|
||||||
|
|
||||||
validates :name, presence: true, uniqueness: true
|
validates :name, presence: true, uniqueness: true
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
class OpenidConnect::ScopeToken < ActiveRecord::Base
|
class OpenidConnect::ScopeToken < ActiveRecord::Base
|
||||||
belongs_to :scope
|
belongs_to :scope
|
||||||
belongs_to :token
|
belongs_to :o_auth_access_token
|
||||||
|
|
||||||
validates :scope, presence: true
|
validates :scope, presence: true
|
||||||
validates :token, presence: true
|
validates :token, presence: true
|
||||||
|
|
|
||||||
|
|
@ -76,9 +76,9 @@ class User < ActiveRecord::Base
|
||||||
|
|
||||||
has_many :reports
|
has_many :reports
|
||||||
|
|
||||||
has_many :authorizations, class_name: 'OpenidConnect::Authorization'
|
has_many :authorizations, class_name: "OpenidConnect::Authorization"
|
||||||
has_many :o_auth_applications, through: :authorizations, class_name: 'OpenidConnect::OAuthApplication'
|
has_many :o_auth_applications, through: :authorizations, class_name: "OpenidConnect::OAuthApplication"
|
||||||
has_many :o_auth_access_tokens, through: :authorizations, class_name: 'OpenidConnect::OAuthAccessToken'
|
has_many :o_auth_access_tokens, through: :authorizations, class_name: "OpenidConnect::OAuthAccessToken"
|
||||||
|
|
||||||
before_save :guard_unconfirmed_email,
|
before_save :guard_unconfirmed_email,
|
||||||
:save_person!
|
:save_person!
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
class CreateOAuthAccessTokens < ActiveRecord::Migration
|
class CreateOAuthAccessTokens < ActiveRecord::Migration
|
||||||
def self.up
|
def self.up
|
||||||
create_table :o_auth_access_tokens do |t|
|
create_table :o_auth_access_tokens do |t|
|
||||||
t.belongs_to :user, index: true
|
t.belongs_to :authorization, index: true
|
||||||
t.belongs_to :authorizations
|
|
||||||
t.belongs_to :endpoints
|
|
||||||
t.string :token
|
t.string :token
|
||||||
t.datetime :expires_at
|
t.datetime :expires_at
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
class CreateAuthorizationsScopesJoinTable < ActiveRecord::Migration
|
class CreateAuthorizationsScopesJoinTable < ActiveRecord::Migration
|
||||||
def change
|
def change
|
||||||
create_table :authorizations_scopes, id: false do |t|
|
create_table :authorizations_scopes, id: false do |t|
|
||||||
t.belongs_to :endpoints, index: true
|
t.belongs_to :authorization, index: true
|
||||||
t.belongs_to :scope, index: true
|
t.belongs_to :scope, index: true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -256,7 +256,6 @@ ActiveRecord::Schema.define(version: 20150708155747) do
|
||||||
add_index "notifications", ["target_type", "target_id"], name: "index_notifications_on_target_type_and_target_id", length: {"target_type"=>190, "target_id"=>nil}, using: :btree
|
add_index "notifications", ["target_type", "target_id"], name: "index_notifications_on_target_type_and_target_id", length: {"target_type"=>190, "target_id"=>nil}, using: :btree
|
||||||
|
|
||||||
create_table "o_auth_access_tokens", force: :cascade do |t|
|
create_table "o_auth_access_tokens", force: :cascade do |t|
|
||||||
t.integer "user_id", limit: 4
|
|
||||||
t.integer "authorization_id", limit: 4
|
t.integer "authorization_id", limit: 4
|
||||||
t.string "token", limit: 255
|
t.string "token", limit: 255
|
||||||
t.datetime "expires_at"
|
t.datetime "expires_at"
|
||||||
|
|
@ -264,7 +263,7 @@ ActiveRecord::Schema.define(version: 20150708155747) do
|
||||||
t.datetime "updated_at", null: false
|
t.datetime "updated_at", null: false
|
||||||
end
|
end
|
||||||
|
|
||||||
add_index "o_auth_access_tokens", ["user_id"], name: "index_o_auth_access_tokens_on_user_id", using: :btree
|
add_index "o_auth_access_tokens", ["authorization_id"], name: "index_o_auth_access_tokens_on_authorization_id", using: :btree
|
||||||
|
|
||||||
create_table "o_auth_applications", force: :cascade do |t|
|
create_table "o_auth_applications", force: :cascade do |t|
|
||||||
t.integer "user_id", limit: 4
|
t.integer "user_id", limit: 4
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ module OpenidConnect
|
||||||
if user
|
if user
|
||||||
if user.valid_password?(req.password)
|
if user.valid_password?(req.password)
|
||||||
auth = OpenidConnect::Authorization.find_or_create(req.client_id, user)
|
auth = OpenidConnect::Authorization.find_or_create(req.client_id, user)
|
||||||
res.access_token = auth.create_token
|
res.access_token = auth.create_access_token
|
||||||
else
|
else
|
||||||
req.invalid_grant!
|
req.invalid_grant!
|
||||||
end
|
end
|
||||||
|
|
@ -40,9 +40,9 @@ module OpenidConnect
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_refresh_flow(req, res)
|
def handle_refresh_flow(req, res)
|
||||||
auth = OpenidConnect::Authorization.find_by_client_id req.client_id
|
auth = OpenidConnect::Authorization.where(client_id: req.client_id).where(refresh_token: req.refresh_token).first
|
||||||
if OpenidConnect::Authorization.valid? req.refresh_token
|
if auth
|
||||||
res.access_token = auth.create_token
|
res.access_token = auth.create_access_token
|
||||||
else
|
else
|
||||||
req.invalid_grant!
|
req.invalid_grant!
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -5,20 +5,20 @@ describe OpenidConnect::ProtectedResourceEndpoint, type: :request do
|
||||||
let!(:client) do
|
let!(:client) do
|
||||||
OpenidConnect::OAuthApplication.create!(name: "Diaspora Test Client", redirect_uris: ["http://localhost:3000/"])
|
OpenidConnect::OAuthApplication.create!(name: "Diaspora Test Client", redirect_uris: ["http://localhost:3000/"])
|
||||||
end
|
end
|
||||||
let(:auth) { OpenidConnect::Authorization.find_or_create(client.client_id, bob) }
|
let!(:auth) { OpenidConnect::Authorization.find_or_create(client.client_id, bob) }
|
||||||
let!(:token) { auth.create_token.to_s }
|
let!(:access_token) { auth.create_access_token.to_s }
|
||||||
let(:invalid_token) { SecureRandom.hex(32).to_s }
|
let!(:invalid_token) { SecureRandom.hex(32).to_s }
|
||||||
# TODO: Add tests for expired access tokens
|
# TODO: Add tests for expired access tokens
|
||||||
|
|
||||||
context "when access token is valid" do
|
context "when access token is valid" do
|
||||||
it "shows the user's username and email" do
|
it "shows the user's username and email" do
|
||||||
get "/api/v0/user/", access_token: token
|
get "/api/v0/user/", access_token: access_token
|
||||||
json_body = JSON.parse(response.body)
|
json_body = JSON.parse(response.body)
|
||||||
expect(json_body["username"]).to eq(bob.username)
|
expect(json_body["username"]).to eq(bob.username)
|
||||||
expect(json_body["email"]).to eq(bob.email)
|
expect(json_body["email"]).to eq(bob.email)
|
||||||
end
|
end
|
||||||
it "should include private in the cache-control header" do
|
it "should include private in the cache-control header" do
|
||||||
get "/api/v0/user/", access_token: token
|
get "/api/v0/user/", access_token: access_token
|
||||||
expect(response.headers["Cache-Control"]).to include("private")
|
expect(response.headers["Cache-Control"]).to include("private")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue