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

Refacto OIDC 3 #1405

Closed
wants to merge 86 commits into from
Closed

Refacto OIDC 3 #1405

wants to merge 86 commits into from

Conversation

natacha-beck
Copy link
Contributor

@natacha-beck natacha-beck commented Jul 4, 2024

@prioux and @MontrealSergiy I think it is now ready for review.

@prioux
Copy link
Member

prioux commented Jul 16, 2024

Can you please include the Globus record in your oidc.yml.rb file please? Also, this file will become part of the official distribution of CBRAIN, so it should contain

  1. a comment block at the top explaining its purpose
  2. all the configs should come with enabled: false, not true like in your commit, otherwise somebody installing a portal would get a non-functionning CBRAIN that crashes with a misconfigured keycloak auth service

# Scope used when called the OpenID provider when autheticate
scope: "openid email profile"
# OpenID provider id and secret need to be passed via environment variables
client_id: <%= ENV["keycloak_client_id"] %>
Copy link
Member

Choose a reason for hiding this comment

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

The examples of ruby code to embed environment variables in the OIDC YAML file should also zap the environment variables, so that they don't get propagated inside the app.

Copy link
Member

Choose a reason for hiding this comment

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

e.g.

client_id: <%= ENV.delete 'keycloak_client_id' %>

Copy link
Member

@prioux prioux Jul 16, 2024

Choose a reason for hiding this comment

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

When I booted my server, I got this in the initial boot messages:

C> Loading OIDC configuration...
C>      - ERROR: Cannot load OIDC configuration.
C>        Missing keys client_secret, client_id in OIDC config: Keycloak
C> CBRAIN BrainPortal validation completed, 2024-07-16 11:34:22 -0400

Yet the application continued to boot. That's wrong, if the admin does not configure this important config file correctly, the server should not continue!

# along with this program. If not, see <http://www.gnu.org/licenses/>.
#

class OidcConfig
Copy link
Member

Choose a reason for hiding this comment

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

This class is not documented.

begin
OidcConfig.load_from_file
rescue => ex
puts "C> \t- ERROR: Cannot load OIDC configuration."
Copy link
Member

Choose a reason for hiding this comment

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

Put a better message here, say something like check the content of "oidc.yml.rb"

Copy link
Member

Choose a reason for hiding this comment

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

Also, make it stop the server boot process.

Copy link
Member

Choose a reason for hiding this comment

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

Also, when enabled is false, it shouldn't complain about anything.

# A OpenID provider can be enabled
enabled: true
# Configuration of the OpenID provider
authorize_uri: "http://localhost:8080/realms/.../protocol/openid-connect/auth"
Copy link
Member

Choose a reason for hiding this comment

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

What are the ... in the path? Ar they things I'm supposed to replace/substitute? What is supposed to go there?


def generate_oidc_login_uri(oidc_providers, redirect_url) #:nodoc:
@oidc_uris = {}
oidc_providers.each { |oidc| @oidc_uris[oidc.name] = oidc_login_uri(oidc, redirect_url)}
Copy link
Member

Choose a reason for hiding this comment

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

When I went to my account page, this line (245) crashed because oidc_providers was nil

Copy link
Member

@prioux prioux Jul 16, 2024

Choose a reason for hiding this comment

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

The stack trace was:

lib/globus_helpers.rb:245:in `generate_oidc_login_uri'
app/controllers/users_controller.rb:98:in `show'
app/controllers/application_controller.rb:115:in `activate_user_time_zone'

Copy link
Member

Choose a reason for hiding this comment

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

It is because in the users controller code, method show, you misspelled one of the instance variables:

    # Array of enabled OIDC providers configurations
    @oidc_configss = OidcConfig.enabled
    # Hash of OIDC uris with the OIDC name as key
    @oidc_uris      = generate_oidc_login_uri(@oidc_configs, globus_url)

(see the @oidc_configss instead of @oidc_configs... )

@prioux
Copy link
Member

prioux commented Jul 16, 2024

My first step in reviewing this PR is to make sure that all features related to Globus have been preserved.

Right now, on my dev system, I have configured a Globus identity provider in the oidc.yml.erb file, and my server boots, but I can't go any further. The 'my account' page doesn't provide any way to link my account it globus.

Original CBRAIN code screenshot:

Screen Shot 2024-07-16 at 13 29 44

This PR's code screenshot:

Screen Shot 2024-07-16 at 13 30 02

provider_name = identity['identity_provider_display_name'] || cb_error("Globus: No identity provider name")
pref_username = identity['preferred_username'] ||
identity['username'] || cb_error("Globus: No preferred username")
provider_id = identity[oidc.identity_provider_key] || cb_error("#{oidc.name}: No identity provider")
Copy link
Member

Choose a reason for hiding this comment

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

Use oidc.identity_info() instead. That is what this method is for. You should try to hide any identity struct accesses by using a method, to make the code cleaner and avoid bugs (like the next comment I will leave about method find_user_with_globus_identity)

# Returns the user object if found; returns a string error message otherwise.
def find_user_with_globus_identity(globus_identity)
def find_user_with_oidc_identity(oidc, identity)
provider_name = identity[oidc.identity_provider_display_name]
Copy link
Member

Choose a reason for hiding this comment

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

Again, use oidc.identity_info() ; the code here crashes because you did not update the method names to say 'NNN_key'. This would not have happend when using identity_info()

@prioux prioux mentioned this pull request Jul 16, 2024
<strong>Provider name:</strong> <%= prov_name %><br>
<strong>Provider user:</strong> <%= prov_user %><br>
<% if @user.id == current_user.id %>
<%= link_to("Unlink this #{oidc.name} identity", unlink_oidc_path(oidc.name, :from => "cb"),
Copy link
Member

Choose a reason for hiding this comment

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

Why is there :from => 'cb', it's not used at all

@natacha-beck
Copy link
Contributor Author

Replaced by #1412

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants