Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/6222 - Endpoint /api/v1/users/sign_out revokes access token and refresh token on request #6241

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions app/models/api_credential.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,19 @@ def is_refresh_token_expired?
refresh_token_expires_at < Time.current
end

# clear tokens
# token argument takes in two strings: api_token and refresh_token
def revoke_token(token)
if (token == "api_token")
update_columns(api_token_digest: nil)
elsif (token == "refresh_token")
update_columns(refresh_token_digest: nil)
else
return nil
end
return token
end

private

# Generate unique tokens and hashes them for secure db storage
Expand Down
20 changes: 20 additions & 0 deletions spec/models/api_credential_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -100,4 +100,24 @@
expect(api_credential.refresh_token_digest).to eq(Digest::SHA256.hexdigest(refresh_token))
end
end

describe "#revoke_token" do
it "sets api token to nil" do
api_token = api_credential.return_new_api_token![:api_token]
api_credential.revoke_token("api_token")

expect(api_credential.api_token_digest).to be_nil
end

it "sets refresh token to nil" do
refresh_token = api_credential.return_new_refresh_token![:refresh_token]
api_credential.revoke_token("refresh_token")

expect(api_credential.refresh_token_digest).to be_nil
end

it "returns nil if token is not found" do
expect(api_credential.revoke_token("invalid_token")).to be_nil
end
end
end
33 changes: 33 additions & 0 deletions spec/requests/api/v1/users/sessions_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,37 @@
end
end
end

path "/api/v1/users/sign_out" do
delete "Signs out a user" do
tags "Sessions"
produces "application/json"
parameter name: :Authorization, in: :header, type: :string, required: true

let(:casa_org) { create(:casa_org) }
let(:volunteer) { create(:volunteer, casa_org: casa_org) }
let(:api_credential) { create(:api_credential, user: volunteer) }
let(:refresh_token) { api_credential.return_new_refresh_token![:refresh_token] }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Er, is this regenerating a refresh token a 2nd time?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think when you create the api credential table for the first time, the token digest fields are nil - at least in dev environment and so that is why I created the seed file to populate them.

I also need the plain text refresh token to be passed in the authorization header for the sign out.


response "200", "user signed out" do
let(:Authorization) { "Bearer #{refresh_token}" }
schema "$ref" => "#/components/schemas/sign_out"
run_test! do |response|
expect(response.content_type).to eq("application/json; charset=utf-8")
expect(response.body).to eq({message: "Signed out successfully."}.to_json)
expect(response.status).to eq(200)
end
end

response "401", "unauthorized" do
let(:Authorization) { "Bearer foo" }
schema "$ref" => "#/components/schemas/sign_out"
run_test! do |response|
expect(response.content_type).to eq("application/json; charset=utf-8")
expect(response.body).to eq({message: "An error occured when signing out."}.to_json)
expect(response.status).to eq(401)
end
end
end
end
end
6 changes: 6 additions & 0 deletions spec/swagger_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@
properties: {
message: {type: :string}
}
},
sign_out: {
type: :object,
properties: {
message: {type: :string}
}
}
}
},
Expand Down
31 changes: 30 additions & 1 deletion swagger/v1/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ components:
type: string
email:
type: string
api_token_expires_at:
token_expires_at:
type: datetime
refresh_token_expires_at:
type: datetime
Expand All @@ -28,6 +28,11 @@ components:
properties:
message:
type: string
sign_out:
type: object
properties:
message:
type: string
paths:
"/api/v1/users/sign_in":
post:
Expand Down Expand Up @@ -61,6 +66,30 @@ paths:
required:
- email
- password
"/api/v1/users/sign_out":
delete:
summary: Signs out a user
tags:
- Sessions
parameters:
- name: Authorization
in: header
required: true
schema:
type: string
responses:
'200':
description: user signed out
content:
application/json:
schema:
"$ref": "#/components/schemas/sign_out"
'401':
description: unauthorized
content:
application/json:
schema:
"$ref": "#/components/schemas/sign_out"
servers:
- url: https://{defaultHost}
variables:
Expand Down
Loading