Giter Club home page Giter Club logo

iiif-auth-v2's Introduction

IIIF Auth 2

IIIF Auth v2 handles IIIF Authorization Flow API 2.0 requests and is an implmementation of DLCS RFC 012

Running

There is a Dockerfile and docker-compose file for running app:

# build docker image
docker build -t iiif-auth-2:local .  

# run image
docker run -it --rm \
    --name iiif-auth-2 \
    -p "8014:80" \
    iiif-auth-2:local

# run via docker-compose
docker compose up

For local debugging the docker-compose.local.yml file can be used, this will start an empty Postgres instance.

docker compose -f docker-compose.local.yml up

Configuration

The following appSetting configuration values are supported:

Name Description Default
OrchestratorRoot Base URI for Orchestrator, used to generate links
DefaultSignificantGestureTitle Fallback title to use on SignificantGesture.cshtml "Click to continue"
DefaultSignificantGestureMessage Fallback message to use on SignificantGesture.cshtml "You will now be redirected to DLCS to login"
Auth__CookieNameFormat Name of issued cookie, {0} value replaced with customer Id "dlcs-auth2-{0}
Auth__SessionTtl Default TTL for sessions + cookies (in seconds) 600
Auth__RefreshThreshold UserSession expiry not refreshed if LastChecked within this number of secs 120
Auth__JwksTtl How long to cache results of JWKS calls for, in secs 600
GesturePathTemplateForDomain Dictionary that allows control of domain-specific significant gesture paths. {customerId} replaced.
OAuthCallbackPathTemplateForDomain Dictionary that allows control of domain-specific oauth2 callback paths. {customerId} + {accessService} replaced.

A note on Dictionarys for domain-specific paths. A key of "Default" serves as fallback but isn't necessary if the default value matches the canonical DLCS path.

Migrations

Migrations can be added by running the following:

cd src/IIIFAuth2

dotnet ef migrations add "{migration-name}" -p IIIFAuth2.API -o Data/Migrations

Migrations are applied on startup, regardless of environment, if "RunMigrations" = "true".

Local Development

This service is an extension of DLCS Protagonist and once deployed will run under the same host as the main DLCS.

Below are steps for running iiif-auth-v2 and Orchestrator locally:

  1. Create a customer_cookie_domain for required customer (e.g. 99). As orchestrator and iiif-auth-v2 will be running on different ports this is necessary as otherwise orchestrator won't see required cookies.
    • INSERT INTO customer_cookie_domains (customer, domains) values (99, 'localhost');
  2. In iiif-auth-v2 set "OrchestratorRoot": "https://localhost:5003" appSetting (default from orchestrator launchSettings)
  3. In orchestrator set "Auth__Auth2ServiceRoot": "https://localhost:7049/auth/v2/" appSetting (default from orchestrator launchSettings)
  4. In orchestrator change the last line of ConfigDrivenAuthPathGenerator.GetAuth2PathForRequest to:
var auth2PathForRequest = request.GetDisplayUrl(path, includeQueryParams: false);
return auth2PathForRequest.Contains("probe") ? auth2PathForRequest : auth2PathForRequest.Replace(host, "localhost:7049");

Point 4 is a hack and should be addressed in a better manner. It is required as the default path rewrite rules won't work as all auth paths aren't on the root domain

iiif-auth-v2's People

Contributors

donaldgray avatar dependabot[bot] avatar

Stargazers

Ulrich Aschl avatar

Watchers

 avatar  avatar Stephen Fraser avatar  avatar

iiif-auth-v2's Issues

Expand RoleProvider logic

To be expanded: Consider "aspects of the request" for IIIF 2.0. e.g.

  • Must be from IP
  • Must be from domain X
  • Inspect path for session-token

Handle OIDC for role provisioning

As stated in [RFC-008] we need to integrate with an oauth 2.0 Authorization Server and parse claims to Roles.

  • Initiate the Authorization Code Flow to render login page
  • Handle callback from Authorization Server
    • We need to validate both the expiry and signature of the JWT token returned from the Authorization Server and suitably handle invalid tokens.
  • Parse id_token and calculate DLCS roles based on claims, in accordance with config from DB. Including the 3 unknownValueBehaviours of:
    • Throw - Throw an exception, preventing the user logging in.
    • UseClaim - Use the value of the claim as the role.
    • Fallback - Use the role(s) as specified in fallbackMapping value, which could be an empty array (the user gets assigned no roles)
  • Create session for user with those specific claims

Handle /logout logic in addition to sign in.
Validate that expired tokens can't be used - periodically check if still valid? e.g. by calling /userinfo

Handle clickthrough AccessService

Implement AccessService for a clickthrough GET /auth/v2/{customer}/{access-service}?origin={origin} operation.

The RoleProvider configuration value will define that this is clickthrough. Render UI for client to render to get user to accept / reject request.

GET endpoints for auth services

Implement GET /auth/v2/service/{asset-id}?role={roles} on AuthService.

This can be called by any service that is generating a IIIF description resource. Initially this will be the Orchestrator, when building info.json + manifests (see dlcs/protagonist#523) but it could be some other middleware that is aware of asset-ids and roles.

The image doesn't need to exist for this to return, this avoids a timing dependency for external middleware building IIIF resources.

Acceptance Criteria:

  • Return 404 if all roles don't exist
  • If multiple roles passed and only some exist, generate as much iiif description resource as possible.
  • Return correct iiif description resource snippet containing ProbeService, AccessService, AccessTokenService

ProbeService (internal/downstream)

As detailed in RFC 012 - IIIF Auth 2, the client will call Orchestrator probe service and the Orchestrator will delegate to this downstream endpoint.

Format of endpoint is: GET /probe/{asset-id}?role={csv-roles}. It will verify whether the user has access to requested resource and return a https://iiif.io/api/auth/2.0/#probe-service-response.

There is no check made to verify whether the specific image has the provided role.

An alternative endpoint for Orchestrator quickly validating whether user has access to requested status or not should be added. This will have similar logic but use provided Cookie rather than access-token to validate a response.

Acceptance Criteria

  • Endpoint to validate Bearer token. Returns probe-service-response.
  • Endpoint to validate Cookie. Returns status code only.

Handle oidc AccessService implementation

Implement AccessService for a oidc GET /auth/v2/{customer}/{access-service}?origin={origin} operation.

This will use the process outlined in RFC 008.

Prior to redirecting to oidc provider we need to render UI to notify user they are being redirect to {somewhere}. This is to record a significant gesture in the DLCS domain - if the ?origin= is the same as the domain the DLCS is hosted on there is no need to do this.

See #5 and #3 as prerequisites

Duplicate of #8 ?

Support alternative Hosts

The Configuration element for a RoleProvider has a "default" top level key.

For IIIF Auth 0.9 and 1.0, implemented in Protagonist, there could be alternative keys that represent different hostnames. Do we want to support this arrangement in this IIIF Auth v2 service? It would mean having the same hostname path configuration as Protagonist, which is a fairly isolated block of code.

Fix gesture path default config

Gesture path config is defaulted to "/access/{customerId}/gesture". This should be aware of pathBase if set, as without that we will always need to configure the path, e.g.

Auth__GesturePathTemplateForDomain__Default=/auth/v2/access/{customerId}/gesture

AccessTokenService

Implement AccessTokenService. The AccessService will have issued the user with a cookie (the 'authorizing aspect'). This cookie is sent to the user, along with origin and messageId query parameters.

The AccessTokenService will render an HTML AccessTokenServiceResponse containing AccessToken (fetched from DB via provided cookie).

If the cookie is not valid, or missing, return an AccessTokenError.

Acceptance Criteria

  • Render HTML Access Token Service Response on receipt of a valid cookie. This should include AccessToken to be presented to ProbeService
  • Render Access Token Error if cookie is missing or invalid.

Set appropriate cached headers

Set appropriate caching headers. In testing some intermediates are caching responses as there are no no-cache set. Confirm which endpoints should never be cached and ensure the appropriate headers are set. e.g. the gesture page shouldn't be cached as it contains a single used token.

Remove expired SessionUsers

All auth interactions will result in the creation of a SessionUser.

These are fairly short lived and have a set expiry. This expiry is extended when they are used, however we could end up with a table full of sessions that have expired.

Create something that clears down expired SessionUser records periodically - this could be done as part of check in webapp or as a separate daemon job.

Better handling of subdomains

The method IsSameOrigin checks if the specified origin header matches the domain the the DLCS is currently running on. This check is to determine if the user needs to carry out a significant gesture on the specified domain.

The logic needs to be expanded to take into account the DLCS being hosted on a different domain. E.g. for wellcome the viewer will be at wellcomecollection.org but the DLCS at iiif.wellcomecollection.org.

This method needs to be expanded to check if the provided origin matches current host, but also to check if the provided origin matches one of the CookieDomains - if the origin is in that list we are safe to set a cookie for that domain.

In addition to altering the logic we need to save the CookieDomains in the database, by customer, so that these can be externally managed.

Handle session logout

Logging out of a session expires the current session and removes cookie from current request.

Update SessionUser for users who get tokens for multiple customers + roles

There might not necessarily be specific work for this but we need to validate that a user can login as multiple different customers, and/or multiple different roles for the same customer (e.g. clickthrough + roleprovider)

Edit - the current iiif-auth-v2 implementation assumes a single session per customer. This has been done as an MVP with clickthrough the only provider. The login logic will need extended to check for the existence of session/cookie and update that as required.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.