-
-
Notifications
You must be signed in to change notification settings - Fork 486
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6216 from 7riumph/feature/6207
Feature/6207 Endpoint api/v1/sign_in now outputs randomized tokens in response upon sign-in
- Loading branch information
Showing
22 changed files
with
305 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,21 @@ | ||
class Api::V1::SessionBlueprint < Blueprinter::Base | ||
identifier :id | ||
field :user do |user| | ||
{ | ||
id: user.id, | ||
display_name: user.display_name, | ||
email: user.email, | ||
refresh_token_expires_at: user.api_credential&.refresh_token_expires_at, | ||
token_expires_at: user.api_credential&.token_expires_at | ||
} | ||
end | ||
|
||
fields :id, :display_name, :email, :token | ||
field :api_token do |user| | ||
token = user.api_credential | ||
token.return_new_api_token![:api_token] | ||
end | ||
|
||
field :refresh_token do |user| | ||
token = user.api_credential | ||
token.return_new_refresh_token![:refresh_token] | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
require "digest" | ||
|
||
class ApiCredential < ApplicationRecord | ||
belongs_to :user | ||
|
||
before_save :generate_api_token | ||
before_save :generate_refresh_token | ||
|
||
# Securely confirm/deny that Hash in db is same as current users token Hash | ||
def authenticate_api_token(api_token) | ||
Digest::SHA256.hexdigest(api_token) == api_token_digest | ||
end | ||
|
||
def authenticate_refresh_token(refresh_token) | ||
Digest::SHA256.hexdigest(refresh_token) == refresh_token_digest | ||
end | ||
|
||
# Securely generate and then return new tokens | ||
def return_new_api_token! | ||
new_token = generate_api_token | ||
update_column(:api_token_digest, api_token_digest) | ||
{api_token: new_token} | ||
end | ||
|
||
def return_new_refresh_token! | ||
new_token = generate_refresh_token | ||
update_column(:refresh_token_digest, refresh_token_digest) | ||
{refresh_token: new_token} | ||
end | ||
|
||
# Verifying token has or has not expired | ||
def is_api_token_expired? | ||
token_expires_at < Time.current | ||
end | ||
|
||
def is_refresh_token_expired? | ||
refresh_token_expires_at < Time.current | ||
end | ||
|
||
private | ||
|
||
# Generate unique tokens and hashes them for secure db storage | ||
def generate_api_token | ||
new_api_token = SecureRandom.hex(18) | ||
self.api_token_digest = Digest::SHA256.hexdigest(new_api_token) | ||
new_api_token | ||
end | ||
|
||
def generate_refresh_token | ||
new_refresh_token = SecureRandom.hex(18) | ||
self.refresh_token_digest = Digest::SHA256.hexdigest(new_refresh_token) | ||
new_refresh_token | ||
end | ||
end | ||
|
||
# == Schema Information | ||
# | ||
# Table name: api_credentials | ||
# | ||
# id :bigint not null, primary key | ||
# api_token_digest :string | ||
# refresh_token_digest :string | ||
# refresh_token_expires_at :datetime | ||
# token_expires_at :datetime | ||
# created_at :datetime not null | ||
# updated_at :datetime not null | ||
# user_id :bigint not null | ||
# | ||
# Indexes | ||
# | ||
# index_api_credentials_on_api_token_digest (api_token_digest) UNIQUE WHERE (api_token_digest IS NOT NULL) | ||
# index_api_credentials_on_refresh_token_digest (refresh_token_digest) UNIQUE WHERE (refresh_token_digest IS NOT NULL) | ||
# index_api_credentials_on_user_id (user_id) | ||
# | ||
# Foreign Keys | ||
# | ||
# fk_rails_... (user_id => users.id) | ||
# |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
module Api | ||
extend ActiveSupport::Concern | ||
included do | ||
has_one :api_credential, dependent: :destroy | ||
after_create :initialize_api_credentials | ||
end | ||
|
||
private | ||
|
||
def initialize_api_credentials | ||
create_api_credential unless api_credential | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
class RemoveTokenFromUsers < ActiveRecord::Migration[7.2] | ||
def change | ||
safety_assured { remove_column :users, :token, :string } | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
class CreateApiCredentials < ActiveRecord::Migration[7.2] | ||
def change | ||
create_table :api_credentials do |t| | ||
t.references :user, null: false, foreign_key: true | ||
t.string :api_token | ||
t.string :refresh_token | ||
t.datetime :token_expires_at, default: -> { "NOW() + INTERVAL '7 hours'" } | ||
t.datetime :refresh_token_expires_at, default: -> { "NOW() + INTERVAL '30 days'" } | ||
|
||
t.string :api_token_digest | ||
t.string :refresh_token_digest | ||
|
||
t.timestamps | ||
end | ||
|
||
add_index :api_credentials, :api_token_digest, unique: true, where: "api_token_digest IS NOT NULL" | ||
add_index :api_credentials, :refresh_token_digest, unique: true, where: "refresh_token_digest IS NOT NULL" | ||
end | ||
end |
6 changes: 6 additions & 0 deletions
6
db/migrate/20250208160513_remove_plain_text_tokens_from_api_credentials.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
class RemovePlainTextTokensFromApiCredentials < ActiveRecord::Migration[7.2] | ||
def change | ||
safety_assured { remove_column :api_credentials, :api_token, :string } | ||
safety_assured { remove_column :api_credentials, :refresh_token, :string } | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
FactoryBot.define do | ||
factory :api_credential do | ||
association :user | ||
api_token_digest { Digest::SHA256.hexdigest(SecureRandom.hex(18)) } | ||
refresh_token_digest { Digest::SHA256.hexdigest(SecureRandom.hex(18)) } | ||
token_expires_at { 1.hour.from_now } | ||
refresh_token_expires_at { 1.day.from_now } | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.