-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor token handling with strategy pattern
Replaced direct JWT encoding/decoding calls with a strategy pattern using a `TokenManager` class and `TokenProvider` interface. This introduces support for multiple token types (JWT and opaque) and centralizes token management. Enhanced configuration to handle different token types and improved error handling with detailed messages for unsupported operations. This change aims to increase code flexibility and maintainability, allowing easy addition of new token strategies in the future.
- Loading branch information
Showing
10 changed files
with
171 additions
and
43 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
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
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,41 @@ | ||
module Authly | ||
# Token Management Class | ||
class TokenManager | ||
@token_provider : TokenProvider | ||
|
||
TOKEN_PROVIDER = { | ||
"jwt" => JWTTokenProvider.new, | ||
"opaque" => OpaqueTokenProvider.new | ||
} | ||
|
||
def initialize | ||
@token_provider = TOKEN_PROVIDER.fetch(Authly.config.token_type) do | ||
raise Error.unsupported_token_type | ||
end | ||
end | ||
|
||
def encode(payload) : String | ||
@token_provider.encode(payload) | ||
end | ||
|
||
def decode(token : String) | ||
@token_provider.decode(token) | ||
end | ||
|
||
def valid?(token : String) : Bool | ||
@token_provider.valid?(token) | ||
end | ||
|
||
def revoke(token : String) | ||
@token_provider.revoke(token) | ||
end | ||
|
||
def revoke?(token : String) : Bool | ||
@token_provider.revoke?(token) | ||
end | ||
|
||
def introspect(token : String) | ||
@token_provider.introspect(token) | ||
end | ||
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,100 @@ | ||
module Authly | ||
module TokenProvider | ||
abstract def encode(payload : Hash(String, String | Bool | Int64)) : String | ||
|
||
abstract def decode(token : String) : Hash(String, String | Bool | Int64) | ||
|
||
abstract def valid?(token : String) : Bool | ||
|
||
abstract def revoke(token : String) | ||
|
||
abstract def revoke?(token : String) : Bool | ||
|
||
abstract def introspect(token : String) : Hash(String, String | Bool | Int64) | ||
end | ||
|
||
# JWT Token Provider | ||
class JWTTokenProvider | ||
include TokenProvider | ||
|
||
def encode(payload : Hash(String, String | Bool | Int64)) : String | ||
JWT.encode(payload, Authly.config.security.secret_key, Authly.config.security.algorithm) | ||
end | ||
|
||
def decode(token : String) : Hash(String, String | Bool | Int64) | ||
decoded_token, _header = JWT.decode(token, Authly.config.security.public_key, Authly.config.security.algorithm) | ||
decoded_token | ||
end | ||
|
||
def valid?(token : String) : Bool | ||
decoded_token, _header = JWT.decode(token, Authly.config.security.public_key, Authly.config.security.algorithm) | ||
exp = decoded_token["exp"].to_s.to_i | ||
Time.utc.to_unix < exp | ||
rescue JWT::DecodeError | ||
false | ||
end | ||
|
||
def revoke(token : String) | ||
Authly.config.providers.jti_provider.revoke(token) | ||
end | ||
|
||
def revoke?(token : String) : Bool | ||
Authly.config.providers.jti_provider.revoked?(token) | ||
end | ||
|
||
def introspect(token : String) : Hash(String, String | Bool | Int64) | ||
payload = decode(token) | ||
active = valid?(token) | ||
{ | ||
"active" => active, | ||
"scope" => payload["scope"], | ||
"cid" => payload["cid"], | ||
"exp" => payload["exp"], | ||
"sub" => payload["sub"] | ||
} | ||
rescue JWT::DecodeError | ||
{"active" => false} | ||
end | ||
end | ||
|
||
# Opaque Token Provider | ||
class OpaqueTokenProvider | ||
include TokenProvider | ||
|
||
def encode(payload : Hash(String, String | Bool | Int64)) : String | ||
token = Random::Secure.hex(32) | ||
Authly.config.providers.jti_provider.store(token, payload) | ||
token | ||
end | ||
|
||
def decode(token : String) : Hash(String, String | Bool | Int64) | ||
Authly.config.providers.jti_provider.fetch(token) || raise Error.invalid_token | ||
end | ||
|
||
def valid?(token : String) : Bool | ||
!Authly.config.providers.jti_provider.revoked?(token) | ||
end | ||
|
||
def revoke(token : String) | ||
Authly.config.providers.jti_provider.revoke(token) | ||
end | ||
|
||
def revoke?(token : String) : Bool | ||
Authly.config.providers.jti_provider.revoked?(token) | ||
end | ||
|
||
def introspect(token : String) : Hash(String, String | Bool | Int64) | ||
payload = decode(token) | ||
active = valid?(token) | ||
{ | ||
"active" => active, | ||
"scope" => payload["scope"], | ||
"cid" => payload["cid"], | ||
"exp" => payload["exp"], | ||
"sub" => payload["sub"] | ||
} | ||
rescue Error | ||
{"active" => false} | ||
end | ||
end | ||
end |