实施用于授权码授予的omniauth策略

时间:2019-03-01 23:38:55

标签: ruby-on-rails ruby-on-rails-3 oauth oauth-2.0 omniauth

我正在尝试使用Omniauth通过Okta实现授权代码授予类型。我实施的策略几乎与okta omniauth gem中的策略相同。我已将必要的代码添加到devise初始化程序中,它可以轻松地从授权端点检索授权代码和授予类型。但是,当它将参数返回给redirect_uri时,我不明白如何获得启动callback_phase方法的策略,而该策略对于与令牌端点交换访问令牌的代码是必需的。结果,未创建auth哈希,因此控制器中的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

initializer / 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)

0 个答案:

没有答案