InstID tokens, part 1: generation
fixes INTEROP-6913, INTEROP-6892, INTEROP-6893, INTEROP-6920
flag = none
This commit introduces the InstID token, a signed and encrypted JWT (aka
JWE) that will soon be usable for Canvas API access (that's "part 2").
If the InstID class is configured with a private signing key and public
encryption key, it will be able to produce encrypted JWTs and validate
and deserialize decrypted JWTs. If it is configured with only a public
signing key, it cannot produce tokens but it can still validate and
deserialize decrypted ones. Therefore this class can be used by the
identity provider (currently Canvas) to produce tokens, but also by any
services that want to use InstID tokens for authentication.
test plan:
1) generate two RSA keypairs. one way to generate a keypair is from a
rails console:
> keypair = Canvas::Security::RSAKeyPair.new
> puts keypair.private_key.to_s
> puts keypair.public_key.to_s
2) choose which one is for signing and which is for encryption, then add
the private signing key and the public encryption key to your rails
credentials:
- run `bin/rails credentials:edit`
- add an entry like the following, and then save and close your
editor:
```
inst_id:
encryption_key: |
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvY1EMlGm1daM87ejGuFX
<...snip...>
/wIDAQAB
-----END PUBLIC KEY-----
signing_key: |
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAnDwED/QOB0f0H6TOZqLmjaPqA7m8c40NDXkAa6u5cK8zCbk3
<...snip...>
QhjPgifBwTrzj21484CfiPfy5oe756Exerj8PIlRrE/hxWRSDwBIOg==
-----END RSA PRIVATE KEY-----
```
3) open a rails console and do:
> id = InstID.for_user('user-uuid')
> id.to_token # make sure this doesn't blow up
> token = id.to_unencrypted_token
> decoded_id = InstID.from_token(token)
> id.jwt_payload == decoded_id.jwt_payload # => true
TODO in followup commits:
- make canvas accept InstID tokens for auth
Change-Id: Ie550c17507c26f9944bd62a747a6a63161e8e770
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/268872
Reviewed-by: Ethan Vizitei <evizitei@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
QA-Review: Michael Ziwisky <mziwisky@instructure.com>
Product-Review: Michael Ziwisky <mziwisky@instructure.com>
2021-07-13 11:46:17 +08:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
#
|
|
|
|
# Copyright (C) 2021 - present Instructure, Inc.
|
|
|
|
#
|
|
|
|
# This file is part of Canvas.
|
|
|
|
#
|
|
|
|
# Canvas is free software: you can redistribute it and/or modify it under
|
|
|
|
# the terms of the GNU Affero General Public License as published by the Free
|
|
|
|
# Software Foundation, version 3 of the License.
|
|
|
|
#
|
|
|
|
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
|
|
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
|
|
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
|
|
|
# details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU Affero General Public License along
|
|
|
|
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
2021-07-22 05:20:34 +08:00
|
|
|
require "inst_access"
|
2023-07-04 03:09:03 +08:00
|
|
|
require_relative "inst_access_support"
|
InstID tokens, part 1: generation
fixes INTEROP-6913, INTEROP-6892, INTEROP-6893, INTEROP-6920
flag = none
This commit introduces the InstID token, a signed and encrypted JWT (aka
JWE) that will soon be usable for Canvas API access (that's "part 2").
If the InstID class is configured with a private signing key and public
encryption key, it will be able to produce encrypted JWTs and validate
and deserialize decrypted JWTs. If it is configured with only a public
signing key, it cannot produce tokens but it can still validate and
deserialize decrypted ones. Therefore this class can be used by the
identity provider (currently Canvas) to produce tokens, but also by any
services that want to use InstID tokens for authentication.
test plan:
1) generate two RSA keypairs. one way to generate a keypair is from a
rails console:
> keypair = Canvas::Security::RSAKeyPair.new
> puts keypair.private_key.to_s
> puts keypair.public_key.to_s
2) choose which one is for signing and which is for encryption, then add
the private signing key and the public encryption key to your rails
credentials:
- run `bin/rails credentials:edit`
- add an entry like the following, and then save and close your
editor:
```
inst_id:
encryption_key: |
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvY1EMlGm1daM87ejGuFX
<...snip...>
/wIDAQAB
-----END PUBLIC KEY-----
signing_key: |
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAnDwED/QOB0f0H6TOZqLmjaPqA7m8c40NDXkAa6u5cK8zCbk3
<...snip...>
QhjPgifBwTrzj21484CfiPfy5oe756Exerj8PIlRrE/hxWRSDwBIOg==
-----END RSA PRIVATE KEY-----
```
3) open a rails console and do:
> id = InstID.for_user('user-uuid')
> id.to_token # make sure this doesn't blow up
> token = id.to_unencrypted_token
> decoded_id = InstID.from_token(token)
> id.jwt_payload == decoded_id.jwt_payload # => true
TODO in followup commits:
- make canvas accept InstID tokens for auth
Change-Id: Ie550c17507c26f9944bd62a747a6a63161e8e770
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/268872
Reviewed-by: Ethan Vizitei <evizitei@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
QA-Review: Michael Ziwisky <mziwisky@instructure.com>
Product-Review: Michael Ziwisky <mziwisky@instructure.com>
2021-07-13 11:46:17 +08:00
|
|
|
|
2021-07-22 05:20:34 +08:00
|
|
|
configure_inst_access = proc do
|
2021-08-07 05:13:25 +08:00
|
|
|
InstAccessSupport.configure_inst_access!
|
InstID tokens, part 1: generation
fixes INTEROP-6913, INTEROP-6892, INTEROP-6893, INTEROP-6920
flag = none
This commit introduces the InstID token, a signed and encrypted JWT (aka
JWE) that will soon be usable for Canvas API access (that's "part 2").
If the InstID class is configured with a private signing key and public
encryption key, it will be able to produce encrypted JWTs and validate
and deserialize decrypted JWTs. If it is configured with only a public
signing key, it cannot produce tokens but it can still validate and
deserialize decrypted ones. Therefore this class can be used by the
identity provider (currently Canvas) to produce tokens, but also by any
services that want to use InstID tokens for authentication.
test plan:
1) generate two RSA keypairs. one way to generate a keypair is from a
rails console:
> keypair = Canvas::Security::RSAKeyPair.new
> puts keypair.private_key.to_s
> puts keypair.public_key.to_s
2) choose which one is for signing and which is for encryption, then add
the private signing key and the public encryption key to your rails
credentials:
- run `bin/rails credentials:edit`
- add an entry like the following, and then save and close your
editor:
```
inst_id:
encryption_key: |
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvY1EMlGm1daM87ejGuFX
<...snip...>
/wIDAQAB
-----END PUBLIC KEY-----
signing_key: |
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAnDwED/QOB0f0H6TOZqLmjaPqA7m8c40NDXkAa6u5cK8zCbk3
<...snip...>
QhjPgifBwTrzj21484CfiPfy5oe756Exerj8PIlRrE/hxWRSDwBIOg==
-----END RSA PRIVATE KEY-----
```
3) open a rails console and do:
> id = InstID.for_user('user-uuid')
> id.to_token # make sure this doesn't blow up
> token = id.to_unencrypted_token
> decoded_id = InstID.from_token(token)
> id.jwt_payload == decoded_id.jwt_payload # => true
TODO in followup commits:
- make canvas accept InstID tokens for auth
Change-Id: Ie550c17507c26f9944bd62a747a6a63161e8e770
Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/268872
Reviewed-by: Ethan Vizitei <evizitei@instructure.com>
Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com>
QA-Review: Michael Ziwisky <mziwisky@instructure.com>
Product-Review: Michael Ziwisky <mziwisky@instructure.com>
2021-07-13 11:46:17 +08:00
|
|
|
end
|
|
|
|
|
2021-07-22 05:20:34 +08:00
|
|
|
Rails.configuration.after_initialize(&configure_inst_access)
|
|
|
|
Canvas::Reloader.on_reload(&configure_inst_access)
|