-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
38 changed files
with
1,048 additions
and
16 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
50 changes: 50 additions & 0 deletions
50
packages/forest_admin_agent/lib/forest_admin_agent/auth/auth_manager.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,50 @@ | ||
require 'json' | ||
|
||
module ForestAdminAgent | ||
module Auth | ||
class AuthManager | ||
def initialize | ||
@oidc = ForestAdminAgent::Auth::OidcClientManager.new | ||
end | ||
|
||
def start(rendering_id) | ||
client = @oidc.make_forest_provider rendering_id | ||
client.authorization_uri({ state: JSON.generate({ renderingId: rendering_id }) }) | ||
end | ||
|
||
def verify_code_and_generate_token(params) | ||
raise Error, ForestAdminAgent::Utils::ErrorMessages::INVALID_STATE_MISSING unless params['state'] | ||
|
||
if Facades::Container.cache(:debug) | ||
OpenIDConnect.http_config do |options| | ||
options.ssl.verify = false | ||
end | ||
end | ||
|
||
rendering_id = get_rendering_id_from_state(params['state']) | ||
|
||
forest_provider = @oidc.make_forest_provider rendering_id | ||
forest_provider.authorization_code = params['code'] | ||
access_token = forest_provider.access_token! 'none' | ||
resource_owner = forest_provider.get_resource_owner access_token | ||
|
||
resource_owner.make_jwt | ||
end | ||
|
||
private | ||
|
||
def get_rendering_id_from_state(state) | ||
state = JSON.parse(state.tr("'", '"').gsub('=>', ':')) | ||
raise Error, ForestAdminAgent::Utils::ErrorMessages::INVALID_STATE_RENDERING_ID unless state.key? 'renderingId' | ||
|
||
begin | ||
Integer(state['renderingId']) | ||
rescue ArgumentError | ||
raise Error, ForestAdminAgent::Utils::ErrorMessages::INVALID_RENDERING_ID | ||
end | ||
|
||
state['renderingId'].to_i | ||
end | ||
end | ||
end | ||
end |
62 changes: 62 additions & 0 deletions
62
packages/forest_admin_agent/lib/forest_admin_agent/auth/oauth2/forest_provider.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,62 @@ | ||
require 'openid_connect' | ||
require_relative 'forest_resource_owner' | ||
|
||
module ForestAdminAgent | ||
module Auth | ||
module OAuth2 | ||
class ForestProvider < OpenIDConnect::Client | ||
attr_reader :rendering_id | ||
|
||
def initialize(rendering_id, attributes = {}) | ||
super attributes | ||
@rendering_id = rendering_id | ||
@authorization_endpoint = '/oidc/auth' | ||
@token_endpoint = '/oidc/token' | ||
self.userinfo_endpoint = "/liana/v2/renderings/#{rendering_id}/authorization" | ||
end | ||
|
||
def get_resource_owner(access_token) | ||
headers = { 'forest-token': access_token.access_token, 'forest-secret-key': secret } | ||
hash = check_response do | ||
OpenIDConnect.http_client.get access_token.client.userinfo_uri, {}, headers | ||
end | ||
|
||
response = OpenIDConnect::ResponseObject::UserInfo.new hash | ||
|
||
create_resource_owner response.raw_attributes[:data] | ||
end | ||
|
||
private | ||
|
||
def create_resource_owner(data) | ||
ForestResourceOwner.new data, rendering_id | ||
end | ||
|
||
def check_response | ||
response = yield | ||
case response.status | ||
when 200 | ||
server_error = response.body.key?('errors') ? response.body['errors'][0] : nil | ||
if server_error && | ||
server_error['name'] == Utils::ErrorMessages::TWO_FACTOR_AUTHENTICATION_REQUIRED | ||
raise Error, Utils::ErrorMessages::TWO_FACTOR_AUTHENTICATION_REQUIRED | ||
end | ||
|
||
response.body.with_indifferent_access | ||
when 400 | ||
raise OpenIDConnect::BadRequest.new('API Access Failed', response) | ||
when 401 | ||
raise OpenIDConnect::Unauthorized.new(Utils::ErrorMessages::AUTHORIZATION_FAILED, response) | ||
when 404 | ||
raise OpenIDConnect::HttpError.new(response.status, Utils::ErrorMessages::SECRET_NOT_FOUND, response) | ||
when 422 | ||
raise OpenIDConnect::HttpError.new(response.status, | ||
Utils::ErrorMessages::SECRET_AND_RENDERINGID_INCONSISTENT, response) | ||
else | ||
raise OpenIDConnect::HttpError.new(response.status, 'Unknown HttpError', response) | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
42 changes: 42 additions & 0 deletions
42
packages/forest_admin_agent/lib/forest_admin_agent/auth/oauth2/forest_resource_owner.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,42 @@ | ||
require 'date' | ||
require 'jwt' | ||
|
||
module ForestAdminAgent | ||
module Auth | ||
module OAuth2 | ||
class ForestResourceOwner | ||
def initialize(data, rendering_id) | ||
@data = data | ||
@rendering_id = rendering_id | ||
end | ||
|
||
def id | ||
@data['id'] | ||
end | ||
|
||
def expiration_in_seconds | ||
(DateTime.now + (1 / 24.0)).to_time.to_i | ||
end | ||
|
||
def make_jwt | ||
attributes = @data['attributes'] | ||
user = { | ||
id: id, | ||
email: attributes['email'], | ||
first_name: attributes['first_name'], | ||
last_name: attributes['last_name'], | ||
team: attributes['teams'][0], | ||
tags: attributes['tags'], | ||
rendering_id: @rendering_id, | ||
exp: expiration_in_seconds, | ||
permission_level: attributes['permission_level'] | ||
} | ||
|
||
JWT.encode user, | ||
Facades::Container.cache(:auth_secret), | ||
'HS256' | ||
end | ||
end | ||
end | ||
end | ||
end |
29 changes: 29 additions & 0 deletions
29
packages/forest_admin_agent/lib/forest_admin_agent/auth/oauth2/oidc_config.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,29 @@ | ||
require 'openid_connect' | ||
|
||
module ForestAdminAgent | ||
module Auth | ||
module OAuth2 | ||
class OidcConfig | ||
def self.discover!(identifier, cache_options = {}) | ||
uri = URI.parse(identifier) | ||
Resource.new(uri).discover!(cache_options).tap do |response| | ||
response.expected_issuer = identifier | ||
response.validate! | ||
end | ||
rescue SWD::Exception, OpenIDConnect::ValidationFailed => e | ||
raise OpenIDConnect::Discovery::DiscoveryFailed, e.message | ||
end | ||
|
||
class Resource < OpenIDConnect::Discovery::Provider::Config::Resource | ||
def initialize(uri) | ||
super | ||
@host = uri.host | ||
@port = uri.port unless [80, 443].include?(uri.port) | ||
@path = File.join uri.path, 'oidc/.well-known/openid-configuration' | ||
attr_missing! | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
71 changes: 71 additions & 0 deletions
71
packages/forest_admin_agent/lib/forest_admin_agent/auth/oidc_client_manager.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,71 @@ | ||
require 'openid_connect' | ||
require_relative 'oauth2/oidc_config' | ||
require_relative 'oauth2/forest_provider' | ||
|
||
module ForestAdminAgent | ||
module Auth | ||
class OidcClientManager | ||
TTL = 60 * 60 * 24 | ||
|
||
def make_forest_provider(rendering_id) | ||
config_agent = Facades::Container.config_from_cache | ||
cache_key = "#{config_agent[:env_secret]}-client-data" | ||
cache = setup_cache(cache_key, config_agent) | ||
|
||
render_provider(cache, rendering_id, config_agent[:env_secret]) | ||
end | ||
|
||
private | ||
|
||
def setup_cache(env_secret, config_agent) | ||
lightly = Lightly.new(life: TTL, dir: "#{config_agent[:cache_dir]}/issuer") | ||
lightly.get env_secret do | ||
oidc_config = retrieve_config(config_agent[:forest_server_url]) | ||
credentials = register( | ||
config_agent[:env_secret], | ||
oidc_config.raw['registration_endpoint'], | ||
{ | ||
token_endpoint_auth_method: 'none', | ||
registration_endpoint: oidc_config.raw['registration_endpoint'], | ||
application_type: 'web' | ||
} | ||
) | ||
|
||
{ | ||
client_id: credentials['client_id'], | ||
issuer: oidc_config.raw['issuer'], | ||
redirect_uri: credentials['redirect_uris'].first | ||
} | ||
end | ||
end | ||
|
||
def register(env_secret, registration_endpoint, data) | ||
response = OpenIDConnect.http_client.post( | ||
registration_endpoint, | ||
data, | ||
{ 'Authorization' => "Bearer #{env_secret}" } | ||
) | ||
|
||
response.body | ||
end | ||
|
||
def render_provider(cache, rendering_id, secret) | ||
OAuth2::ForestProvider.new( | ||
rendering_id, | ||
{ | ||
identifier: cache[:client_id], | ||
redirect_uri: cache[:redirect_uri], | ||
host: cache[:issuer].to_s.sub(%r{^https?://(www.)?}, ''), | ||
secret: secret | ||
} | ||
) | ||
end | ||
|
||
def retrieve_config(uri) | ||
OAuth2::OidcConfig.discover! uri | ||
rescue OpenIDConnect::Discovery::DiscoveryFailed | ||
raise Error, ForestAdminAgent::Utils::ErrorMessages::SERVER_DOWN | ||
end | ||
end | ||
end | ||
end |
19 changes: 19 additions & 0 deletions
19
packages/forest_admin_agent/lib/forest_admin_agent/facades/container.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,19 @@ | ||
module ForestAdminAgent | ||
module Facades | ||
class Container | ||
def self.instance | ||
ForestAdminAgent::Builder::AgentFactory.instance.container | ||
end | ||
|
||
def self.config_from_cache | ||
instance.resolve(:cache).get('config') | ||
end | ||
|
||
def self.cache(key) | ||
raise "Key #{key} not found in container" unless config_from_cache.key?(key) | ||
|
||
config_from_cache[key] | ||
end | ||
end | ||
end | ||
end |
6 changes: 5 additions & 1 deletion
6
packages/forest_admin_agent/lib/forest_admin_agent/http/router.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
3 changes: 0 additions & 3 deletions
3
packages/forest_admin_agent/lib/forest_admin_agent/routes/abstract_route.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
Oops, something went wrong.