Реализация всеобъемлющей стратегии для предоставления кода авторизации - PullRequest
0 голосов
/ 02 марта 2019

Я пытаюсь использовать Omniauth для реализации кода авторизации типа grant через Okta.Я реализовал стратегию, которая почти идентична стратегии в кристалле okta omniauth.Я добавил необходимый код в инициализатор устройства, и он легко извлекает код авторизации и тип предоставления из конечной точки авторизации.Однако, когда он возвращает параметры в redirect_uri, я не понимаю, как заставить стратегию инициировать метод callback_phase, который необходим для обмена кода для токена доступа с конечной точкой токена.В результате хэш аутентификации не создается, поэтому вызов User.from_omniauth в моем контроллере выдает ошибку.

Вопрос: Как мне доставить код доступа в мою стратегию для получения токена доступа?

Любая помощь будет принята с благодарностью.

Стратегия: требуется 'omniauth' требует 'net / http'

# frozen_string_literal: true

require 'omniauth-oauth2'

module OmniAuth
  module Strategies
    class Moto < OmniAuth::Strategies::OAuth2

      ORG           = AUTH['oauth2']['moto']['OKTA_ORG']    || 'your-org'
      DOMAIN        = AUTH['oauth2']['moto']['OKTA_DOMAIN'] || "https://#{ORG}.okta.com"
      BASE_URL      = DOMAIN
      DEFAULT_SCOPE = %[openid profile email].freeze

      option :name, 'moto'

      option :skip_jwt, false
      option :jwt_leeway, 60
      option :redirect_uri, AUTH['oauth2']['moto']['redirect']

      option :client_options, {
        site:          BASE_URL,
        authorize_url: "#{BASE_URL}/oauth2/v1/authorize",
        token_url:     "#{BASE_URL}/oauth2/v1/token",
        response_type: 'authorization_code'
      }

      option :scope, DEFAULT_SCOPE

      uid { raw_info['sub'] }

      info do
        {
          name:       raw_info['name'],
          email:      raw_info['email'],
          first_name: raw_info['given_name'],
          last_name:  raw_info['family_name'],
          image:      raw_info['picture']
        }
      end

      extra do
        hash = {}
        hash[:raw_info] = raw_info unless skip_info?
        hash[:id_token] = access_token.token
        if !options[:skip_jwt] && !access_token.token.nil?
          hash[:id_info] = validated_token(access_token.token)
        end
        hash
      end

      alias :oauth2_access_token :access_token

      def access_token
        puts "in access token"
        ::OAuth2::AccessToken.new(client, oauth2_access_token.token, {
          :refresh_token => oauth2_access_token.refresh_token,
          :expires_in    => oauth2_access_token.expires_in,
          :expires_at    => oauth2_access_token.expires_at
        })
      end

      def raw_info
        @_raw_info ||= access_token.get('/oauth2/v1/userinfo').parsed || {}
      rescue ::Errno::ETIMEDOUT
        raise ::Timeout::Error
      end

      def request_phase
        puts "In request phase"
        super
      end

      def callback_phase
        puts "in callback phase"
        build_access_token
        super
      end

      def callback_url
        options[:redirect_uri] || (full_host + script_name + callback_path)
      end

      def validated_token(token)
        JWT.decode(token,
                   nil,
                   false,
                   verify_iss:        true,
                   iss:               BASE_URL,
                   verify_aud:        true,
                   aud:               BASE_URL,
                   verify_sub:        true,
                   verify_expiration: true,
                   verify_not_before: true,
                   verify_iat:        true,
                   verify_jti:        false,
                   leeway:            options[:jwt_leeway]
                   ).first
      end
    end
  end
end

обратный вызов контроллера

class OmniauthController < Devise::OmniauthCallbacksController
def moto_callback
    # You need to implement the method below in your model (e.g. app/models/user.rb)
    puts "Request env #{env['omniauth.auth']}"
    logger.debug "Request env #{env['omniauth.auth']}"
    @user = User.from_omniauth(request.env["omniauth.auth"])
    print(@user)
    if @user.save
        session[:oktastate] = request.env["omniauth.auth"]
        print(@user.oauth_permissions(session[:oktastate]))
    else
        print(@user.errors.full_messages)
    end
    if @user.persisted?
        redirect_to "/users"
    end
end
end

инициализатор /devise.rb

config.omniauth(:moto, AUTH['oauth2']['moto']['OKTA_CLIENT_ID'], AUTH['oauth2']['moto']['OKTA_CLIENT_SECRET'], :scope => 'openid profile email', :fields => ['profile', 'email'], :strategy_class => OmniAuth::Strategies::Moto)
...