- Remove `Lti::Ims::NamesAndRolesController`'s inclusion of
`Lti::Ims::AccessTokenHelper` in favor of a recently
introduced concern: `Lti::Ims::Concerns::AdvantageServices`. This
includes a reimplementation of `Lti::Oauth2::AccessToken` as
`Lti::Ims::Concerns::AdvantageServices::AccessToken`, which has
many of the same capabilities, but none of the LTI 2 baggage.
- Most low-level JWT validation is delegated to `Canvas::Security`
and `Canvas::Security::JwtValidator`. The former provides symmetry
with `Canvas::Oauth::ClientCredentialsProvider` eso w/r/t using
Canvas encryption keys as signing keys. The latter also aligns well
with that same provider, though its `jti` handling may need to
be relaxed in the future.
- ***This commit intentionally avoids extensive modifications to
`Lti::Ims::Concerns::GradebookServices` and related controllers. The
expectation is that `GradebookServices` should just include
`AdvantageServices` and could thus eliminate many of its methods.
But this has been deferred, partly to keep commit size down and
partly to avoid unilateral contract changes to dependent controllers.
- Most of this commit, then, is really just suffling tests around
from `names_and_roles_controller_spec.rb` into
`advantage_services_shared_examples.rb` so other LTI Advantage
controllers can integrate the same validations.
`advantage_services_shared_context.rb` expresses the data setup
needs of `advantage_services_shared_examples.rb`, along with a few
helper methods.
- Eliminates custom tool/account chain walking in
`NamesAndRolesController` in favor of
`ContextExternalTool#all_tools_for`. Latter's use is in
`AdvantageServices`, so should be readily reusable from other
LTI Advantage controllers.
Closes LTIA-28
Test Plan
* This is largely a technical refactoring so testing should focus
primarily on regression checks against NRPS v2 callbacks, especially
to ensure they still require valid access tokens issues via
client credentials.
* Functional differences are limited to newly added validation of
JWT claims embedded in those access tokens. These are difficult to
test since Canvas is responsible for generating the tokens. So
either Canvas code needs to be temporarily modified to generate
variously incorrect access tokens, or an out of band tool needs to
be implemented to generate such tokens. Claims to be validated:
1. `sub` - must be an active developer key's global ID, e.g.
"10000000000020"
2. `aud` - must be the OAuth2 access token issuance URL, i.e.
`<host>/login/oauth2/token`
3. `iat` - must be in the past
4. `exp` - must be in the future
5. `jti` - must be present
6. `scopes` - must include
https://purl.imsglobal.org/spec/lti-nrps/scope/contextmembership.readonly
7. <signature> - Must use `HS256` algorithm and use the Canvas
encryption key as the signing secret.
Change-Id: I14b431e11180f06e9edd4f5dfd3b04ed931ea73e
Reviewed-on: https://gerrit.instructure.com/167361
Tested-by: Jenkins
QA-Review: Samuel Barney <sbarney@instructure.com>
Reviewed-by: Marc Phillips <mphillips@instructure.com>
Product-Review: Karl Lloyd <karl@instructure.com>