Commit 90deb0b

mo <mo.khan@gmail.com>
2018-09-09 18:18:07
exchange a code for an access/refresh token
1 parent 8c53db7
app/controllers/oauths_controller.rb
@@ -21,11 +21,18 @@ class OauthsController < ApplicationController
   def token
     response.headers['Cache-Control'] = 'no-store'
     response.headers['Pragma'] = 'no-cache'
-    Authorization.find_by!(code: params[:code]).revoke!
-    #@access_token, @refresh_token = Authorization.find_by!(code: params[:code]).exchange
+    if token_params[:grant_type] == 'authorization_code'
+      @access_token, @refresh_token = Authorization.find_by!(code: token_params[:code]).exchange
+    end
     render formats: :json
   rescue StandardError => error
     Rails.logger.error(error)
     render "bad_request", formats: :json, status: :bad_request
   end
+
+  private
+
+  def token_params
+    params.permit(:grant_type, :code)
+  end
 end
app/models/authorization.rb
@@ -4,11 +4,22 @@ class Authorization < ApplicationRecord
   has_secure_token :code
   belongs_to :user
   belongs_to :client
+  has_many :tokens
 
   after_initialize do
     self.expired_at = 10.minutes.from_now unless expired_at.present?
   end
 
+  def exchange
+    transaction do
+      revoke!
+      [
+        tokens.create(subject: user, audience: client, token_type: :access),
+        tokens.create(subject: user, audience: client, token_type: :refresh),
+      ]
+    end
+  end
+
   def revoke!
     raise 'already revoked' if revoked?
     update!(revoked_at: Time.now)
app/models/token.rb
@@ -1,5 +1,6 @@
 class Token < ApplicationRecord
   enum token_type: { access: 0, refresh: 1 }
+  belongs_to :authorization
   belongs_to :subject, polymorphic: true
   belongs_to :audience, polymorphic: true
 
@@ -8,7 +9,9 @@ class Token < ApplicationRecord
 
   after_initialize do |x|
     x.uuid = SecureRandom.uuid if x.uuid.nil?
-    x.expired_at = 1.hour.from_now if x.expired_at.nil?
+    if x.expired_at.nil?
+      x.expired_at = access? ? 1.hour.from_now  : 1.day.from_now
+    end
   end
 
   def revoke!
app/views/oauths/token.json.jbuilder
@@ -1,4 +1,4 @@
-json.access_token SecureRandom.hex(20)
+json.access_token @access_token.to_jwt
 json.token_type 'Bearer'
 json.expires_in 1.hour.to_i
-json.refresh_token SecureRandom.hex(20)
+json.refresh_token @refresh_token.to_jwt
db/migrate/20180909173139_create_tokens.rb
@@ -2,6 +2,7 @@ class CreateTokens < ActiveRecord::Migration[5.2]
   def change
     create_table :tokens do |t|
       t.string :uuid, index: { unique: true }
+      t.references :authorization
       t.references :subject, polymorphic: true
       t.references :audience, polymorphic: true
       t.integer :token_type, default: 0
db/schema.rb
@@ -46,6 +46,7 @@ ActiveRecord::Schema.define(version: 2018_09_09_173139) do
 
   create_table "tokens", force: :cascade do |t|
     t.string "uuid"
+    t.integer "authorization_id"
     t.string "subject_type"
     t.integer "subject_id"
     t.string "audience_type"
@@ -56,6 +57,7 @@ ActiveRecord::Schema.define(version: 2018_09_09_173139) do
     t.datetime "created_at", null: false
     t.datetime "updated_at", null: false
     t.index ["audience_type", "audience_id"], name: "index_tokens_on_audience_type_and_audience_id"
+    t.index ["authorization_id"], name: "index_tokens_on_authorization_id"
     t.index ["subject_type", "subject_id"], name: "index_tokens_on_subject_type_and_subject_id"
     t.index ["uuid"], name: "index_tokens_on_uuid", unique: true
   end
spec/factories.rb
@@ -1,6 +1,7 @@
 FactoryBot.define do
   factory :token do
     uuid { SecureRandom.uuid }
+    association :authorization
     association :audience, factory: :client
     association :subject, factory: :user