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

Add SAML2 auth #2511

Closed
wants to merge 4 commits into from
Closed

Add SAML2 auth #2511

wants to merge 4 commits into from

Commits on Aug 30, 2024

  1. ADD support for SAML2 auth

    This has two components, a regular Webwork Authen module and a
    Mojolicious plugin for SAML2.
    
    The plugin implements a SAML2 SP using the Net::SAML2 library.
    Net::SAML2 claims to be compatible with many SAML2 implementations,
    including Shibboleth.  The intent for this plugin is to replace the old
    Shibboleth auth that depended on the shibd service which requires
    Apache's mod_shib.
    
    The WeBWorK::Authen::Saml2 authen module's main purpose is to call the
    Saml2 plugin helper sendLoginRequest() that properly sends the user to
    the IdP to authenticate. There is a bypass option that allows skipping
    the Saml2 authen in favour of the authen module after it. So you can,
    for example, put Basic_TheLastOption after it allow access to the
    internal username/password auth.
    
    It seems to be standard for Mojolicous plugins to be located in
    lib/Mojolicious/Plugin, so I've put the Saml2 plugin there. Additional
    detail and configuration instructions can be found in
    lib/Mojolicious/Plugin/Saml2/README.md
    
    The Saml2 plugin will only be loaded if the corresponding conf file
    exists. Copy conf/authen_saml2.dist.yml to conf/authen_saml2.yml to
    enable it. 3 settings in the conf are crucial, the idp.metadata_url must
    be set to the IdP's xml metadata endpoint and a unique sp.cert &
    sp.signing_key pair should be generated. The example cert and
    signing_key must not be used for prod under any circumstances.
    
    I initially put the config in conf/mojolicious.webwork.yml under a saml2
    section but seeing as how other authen modules have their own conf
    files, I figure it was better to follow that convention. And as there
    seems to be more work around the yaml config, I've made the saml2 authen
    conf also a yaml file.  The NotYAMLConfig plugin for reading yaml conf
    files gave me some trouble though, as I didn't want to step on the main
    conf and had to read the code to figure out how to use just the load
    conf file functionality.
    
    The Saml2 plugin will generate its own xml metadata that can be used by
    the IdP for configuration. This is available at the /saml2/metadata URL
    under the default config. Note that endpoints are configurable as I
    wanted to be able to change them to match shibd endpoints.
    
    The Saml2 plugin has its own set of controllers and a router for them.
    The AcsPostController is the most important one as it handles the
    SAMLResponse that sends the user back to Webwork from the IdP. The
    errors aren't the most friendly unfortunately, should probably add a
    proper 401 error template so users don't see the more scary stacktrace
    one.
    
    Note that unlike shibd, attribute maps are not supported. So you
    probably have to replace user friendly attribute names like
    "studentNumber" with URN style names like
    "urn:mace:dir:attribute-def:studentNumber". You can check your IdP's
    attribute map xml for the official URN names.
    
    Some discussion about alternatives that I tried before settling on the
    Mojolicious plugin approach:
    
    The Saml2 as a plugin idea started after trying out
    Mojolicious::Plugin::SAML.  Mojolicious::Plugin::SAML didn't work out in
    the end due to two downsides. The major one being a lack of RelayState
    support. RelayState is the defacto standard way for SPs to store where
    the user wants to go after returning from a successful auth from the
    IdP. This is a necessary feature for Webwork as auth to each course is
    handled separately and we need to know exactly what course the user
    wants to get into. The minor issue is that it doesn't parse the
    SAMLResponse attributes for you and I really didn't want to have to muck
    with xml parsing.
    
    Apache mod_proxy using mod_shib and shibd was another possibility. This
    requires passing shib params through HTTP headers via the use of the
    ShibUseHeaders setting. Shibboleth documentation says the ShibUseHeaders
    option should be avoided as they're not confident in the protections
    against spoofed HTTP header attacks.
    
    Running Webwork under mod_perl again so we don't need to use mod_proxy.
    This resulted in hard to debug issues with a few sections of async code.
    While I was able to 'unasync' those sections to get the thing running,
    it feels unmaintainable in the long run, especially if Webwork increases
    usage of async features.
    ionparticle committed Aug 30, 2024
    Configuration menu
    Copy the full SHA
    0cbd050 View commit details
    Browse the repository at this point in the history
  2. FIX WEBWORK_ROOT_URL typo

    WEBWORK_ROOT_URL definition in Dockerfiles used two colons before the
    port when it's supposed to be only 1.
    
    Also deleted version line from docker-compose.dist.yml, as I get a
    warning message that `version` is obsolete.
    ionparticle committed Aug 30, 2024
    Configuration menu
    Copy the full SHA
    29c7b1f View commit details
    Browse the repository at this point in the history
  3. FIX saml2 plugin code review issues

    Mojo::Base's -strict option removed where -signature is present as it
    makes strict redundant.
    
    Use Mojo::JSON's functions instead of JSON.
    
    When using WeBWorK::Debug, specify import of debug() function.
    
    Remove import of WeBWorK::Debug and Data::Dumper where they're not
    actually being used.
    
    Fix README.md to pass markdownlint inspection.
    ionparticle committed Aug 30, 2024
    Configuration menu
    Copy the full SHA
    5ae8626 View commit details
    Browse the repository at this point in the history
  4. FIX docker-config/idp whitespace reformat

    Reformatted to follow .editorconfig rules.
    ionparticle committed Aug 30, 2024
    Configuration menu
    Copy the full SHA
    819b5e5 View commit details
    Browse the repository at this point in the history