diff --git a/Gemfile.d/app.rb b/Gemfile.d/app.rb index d80402329b4..19c4328e919 100644 --- a/Gemfile.d/app.rb +++ b/Gemfile.d/app.rb @@ -77,7 +77,7 @@ gem "neighbor", "~> 0.3" gem "net-http", "~> 0.1", require: false gem "net-ldap", "~> 0.18", require: false gem "oauth", "~> 1.1", require: false -gem "oauth2", "~> 1.4", require: false +gem "oauth2", "~> 2.0", require: false gem "oj", "~> 3.16" gem "outrigger", "3.0.1" gem "parallel", "~> 1.23", require: false diff --git a/Gemfile.lock b/Gemfile.lock index 2cd3d9553f5..b24b853bcb1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -745,12 +745,13 @@ GEM version_gem (~> 1.1) oauth-tty (1.0.5) version_gem (~> 1.1, >= 1.1.1) - oauth2 (1.4.11) + oauth2 (2.0.9) faraday (>= 0.17.3, < 3.0) jwt (>= 1.0, < 3.0) - multi_json (~> 1.3) multi_xml (~> 0.5) rack (>= 1.2, < 4) + snaky_hash (~> 2.0) + version_gem (~> 1.1) oj (3.16.1) once-ler (2.0.1) activerecord (>= 6.0, < 7.1) @@ -1256,7 +1257,7 @@ DEPENDENCIES net-http (~> 0.1) net-ldap (~> 0.18) oauth (~> 1.1) - oauth2 (~> 1.4) + oauth2 (~> 2.0) oj (~> 3.16) once-ler (= 2.0.1) outrigger (= 3.0.1) diff --git a/app/models/authentication_provider/apple.rb b/app/models/authentication_provider/apple.rb index 31cddd2f6a4..c26b6754a48 100644 --- a/app/models/authentication_provider/apple.rb +++ b/app/models/authentication_provider/apple.rb @@ -73,7 +73,7 @@ class AuthenticationProvider::Apple < AuthenticationProvider::OpenIDConnect end user = JSON.parse(params[:user]) if params[:user] - id_token.merge!(user["name"].slice("firstName", "lastName")) if user["name"] + id_token.merge!(user["name"].slice("firstName", "lastName")) if user && user["name"] id_token end @@ -81,14 +81,6 @@ class AuthenticationProvider::Apple < AuthenticationProvider::OpenIDConnect token end - def generate_authorize_url(redirect_uri, state) - # wtf Apple https://forums.developer.apple.com/thread/122458 - # we _could_ update faraday, which has been fixed to deal with this as well, - # but that's a long rabbit whole of other gems that would need updating and - # have very large breaking changes, so far riskier - super.gsub("+", "%20") - end - protected def authorize_url diff --git a/app/models/authentication_provider/linked_in.rb b/app/models/authentication_provider/linked_in.rb index 2e230987085..b15bc83bba9 100644 --- a/app/models/authentication_provider/linked_in.rb +++ b/app/models/authentication_provider/linked_in.rb @@ -92,8 +92,9 @@ class AuthenticationProvider::LinkedIn < AuthenticationProvider::OAuth2 def client_options { site: "https://api.linkedin.com", - authorize_url: "https://www.linkedin.com/uas/oauth2/authorization", - token_url: "https://www.linkedin.com/uas/oauth2/accessToken" + authorize_url: "https://www.linkedin.com/oauth/v2/authorization", + token_url: "https://www.linkedin.com/oauth/v2/accessToken", + auth_scheme: :request_body } end diff --git a/app/models/authentication_provider/oauth.rb b/app/models/authentication_provider/oauth.rb index 00e7b05caee..bfc9505b7a1 100644 --- a/app/models/authentication_provider/oauth.rb +++ b/app/models/authentication_provider/oauth.rb @@ -19,7 +19,6 @@ # require "oauth2" -require "canvas/core_ext/oauth2" class AuthenticationProvider::OAuth < AuthenticationProvider::Delegated SENSITIVE_PARAMS = [:consumer_secret].freeze diff --git a/app/models/authentication_provider/oauth2.rb b/app/models/authentication_provider/oauth2.rb index 0aacb15f3d2..1bbdfba8ccb 100644 --- a/app/models/authentication_provider/oauth2.rb +++ b/app/models/authentication_provider/oauth2.rb @@ -19,7 +19,6 @@ # require "oauth2" -require "canvas/core_ext/oauth2" class OAuthValidationError < RuntimeError end diff --git a/app/models/authentication_provider/open_id_connect.rb b/app/models/authentication_provider/open_id_connect.rb index 496ac967ae5..a6eddf5258b 100644 --- a/app/models/authentication_provider/open_id_connect.rb +++ b/app/models/authentication_provider/open_id_connect.rb @@ -112,11 +112,15 @@ class AuthenticationProvider::OpenIDConnect < AuthenticationProvider::OAuth2 { scope: scope_for_options } end + def client_options + super.merge(auth_scheme: :request_body) + end + private def claims(token) token.options[:claims] ||= begin - jwt_string = token.params["id_token"] + jwt_string = token.params["id_token"] || token.token debug_set(:id_token, jwt_string) if instance_debugging id_token = {} if jwt_string.blank? diff --git a/lib/canvas/core_ext/oauth2.rb b/lib/canvas/core_ext/oauth2.rb deleted file mode 100644 index 21b4837b854..00000000000 --- a/lib/canvas/core_ext/oauth2.rb +++ /dev/null @@ -1,44 +0,0 @@ -# frozen_string_literal: true - -# -# Copyright (C) 2016 - 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 . - -module Canvas::CoreExt - module OAuth2 - def get_token(params, access_token_opts = {}, access_token_class = ::OAuth2::AccessToken) - params = ::OAuth2::Authenticator.new(id, secret, options[:auth_scheme]).apply(params) - opts = { raise_errors: options[:raise_errors], parse: params.delete(:parse) } - headers = params.delete(:headers) || {} - if options[:token_method] == :post - opts[:body] = params - opts[:headers] = { "Content-Type" => "application/x-www-form-urlencoded" } - else - opts[:params] = params - opts[:headers] = {} - end - opts[:headers].merge!(headers) - response = request(options[:token_method], token_url, opts) - # only change is on this line; Microsoft doesn't send back an access_token if you're doing a pure OpenID Connect auth - if options[:raise_errors] && !((response.parsed.is_a?(Hash) && response.parsed["access_token"]) || response.parsed["id_token"]) - error = ::OAuth2::Error.new(response) - raise(error) - end - access_token_class.from_hash(self, response.parsed.merge(access_token_opts)) - end - end -end -OAuth2::Client.prepend(Canvas::CoreExt::OAuth2) diff --git a/spec/models/authentication_provider/open_id_connect_spec.rb b/spec/models/authentication_provider/open_id_connect_spec.rb index d7d4936b875..7a53382ba87 100644 --- a/spec/models/authentication_provider/open_id_connect_spec.rb +++ b/spec/models/authentication_provider/open_id_connect_spec.rb @@ -62,7 +62,7 @@ describe AuthenticationProvider::OpenIDConnect do it "returns nil if the id_token is missing" do connect = described_class.new - uid = connect.unique_id(double(params: { "id_token" => nil }, options: {})) + uid = connect.unique_id(instance_double(OAuth2::AccessToken, params: { "id_token" => nil }, token: nil, options: {})) expect(uid).to be_nil end end