# Varation on {Google::Auth::UserAuthorizer} adapted for Plack based
# web applications.
#
# Example usage:
#
#     get('/') do
#       user_id = request.session['user_email']
#       credentials = authorizer.get_credentials(user_id, request)
#       if credentials.nil?
#         redirect authorizer.get_authorization_url(user_id: user_id,
#                                                   request: request)
#       end
#       # Credentials are valid, can call APIs
#       ...
#    end
#
#    get('/oauth2callback') do
#      url = Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(
#        request)
#      redirect url
#    end
#
# Instead of implementing the callback directly, applications are
# encouraged to use {Google::Auth::WebUserAuthorizer::CallbackApp} instead.
#
# @see CallbackApp
# @note Requires sessions are enabled
class WebUserAuthorizer < Google::Auth::UserAuthorizer
  STATE_PARAM = "state".freeze
  AUTH_CODE_KEY = "code".freeze
  ERROR_CODE_KEY = "error".freeze
  SESSION_ID_KEY = "session_id".freeze
  CALLBACK_STATE_KEY = "g-auth-callback".freeze
  CURRENT_URI_KEY = "current_uri".freeze
  XSRF_KEY = "g-xsrf-token".freeze
  SCOPE_KEY = "scope".freeze

  NIL_REQUEST_ERROR = "Request is required.".freeze
  NIL_SESSION_ERROR = "Sessions must be enabled".freeze
  MISSING_AUTH_CODE_ERROR = "Missing authorization code in request".freeze
  AUTHORIZATION_ERROR = "Authorization error: %s".freeze
  INVALID_STATE_TOKEN_ERROR =
    "State token does not match expected value".freeze

  class << self
    attr_accessor :default
  end
def get_authorization_url options = {}
  options = options.dup
  request = options[:request]
  raise NIL_REQUEST_ERROR if request.nil?
  raise NIL_SESSION_ERROR if request.session.nil?

  state = options[:state] || {}

  redirect_to = options[:redirect_to] || request.url
  request.session[XSRF_KEY] = SecureRandom.base64
  options[:state] = MultiJson.dump(state.merge(
                                     SESSION_ID_KEY  => request.session[XSRF_KEY],
                                     CURRENT_URI_KEY => redirect_to
                                   ))
  options[:base_url] = request.url
  super options
end
def get_credentials user_id, request = nil, scope = nil
  if request&.session&.key? CALLBACK_STATE_KEY
    # Note - in theory, no need to check required scope as this is
    # expected to be called immediately after a return from authorization
    state_json = request.session.delete CALLBACK_STATE_KEY
    callback_state = MultiJson.load state_json
    WebUserAuthorizer.validate_callback_state callback_state, request
    get_and_store_credentials_from_code(
      user_id:  user_id,
      code:     callback_state[AUTH_CODE_KEY],
      scope:    callback_state[SCOPE_KEY],
      base_url: request.url
    )
  else
    super user_id, scope
  end
end
def self.extract_callback_state request
  state = MultiJson.load(request[STATE_PARAM] || "{}")
  redirect_uri = state[CURRENT_URI_KEY]
  callback_state = {
    AUTH_CODE_KEY  => request[AUTH_CODE_KEY],
    ERROR_CODE_KEY => request[ERROR_CODE_KEY],
    SESSION_ID_KEY => state[SESSION_ID_KEY],
    SCOPE_KEY      => request[SCOPE_KEY]
  }
  [callback_state, redirect_uri]
end
def self.validate_callback_state state, request
  raise Signet::AuthorizationError, MISSING_AUTH_CODE_ERROR if state[AUTH_CODE_KEY].nil?
  if state[ERROR_CODE_KEY]
    raise Signet::AuthorizationError,
          format(AUTHORIZATION_ERROR, state[ERROR_CODE_KEY])
  elsif request.session[XSRF_KEY] != state[SESSION_ID_KEY]
    raise Signet::AuthorizationError, INVALID_STATE_TOKEN_ERROR
  end
end
    # Small Plack app which acts as the default callback handler for the app.
    #
    # To configure in Rails, add to routes.rb:
    #
    #     match '/oauth2callback',
    #           to: Google::Auth::WebUserAuthorizer::CallbackApp,
    #           via: :all
    #
    # With Rackup, add to config.ru:
    #
    #     map '/oauth2callback' do
    #       run Google::Auth::WebUserAuthorizer::CallbackApp
    #     end
    #
    # Or in a classic Sinatra app:
    #
    #     get('/oauth2callback') do
    #       Google::Auth::WebUserAuthorizer::CallbackApp.call(env)
    #     end
    #
    # @see Google::Auth::WebUserAuthorizer
    class CallbackApp
      LOCATION_HEADER = "Location".freeze
      REDIR_STATUS = 302
      ERROR_STATUS = 500

      # Handle a rack request. Simply stores the results the authorization
      # in the session temporarily and redirects back to to the previously
      # saved redirect URL. Credentials can be later retrieved by calling.
      # {Google::Auth::Web::WebUserAuthorizer#get_credentials}
      #
      # See {Google::Auth::Web::WebUserAuthorizer#get_authorization_uri}
      # for how to initiate authorization requests.
      #
      # @param [Hash] env
      #  Rack environment
      # @return [Array]
      #  HTTP response
      def self.call env
        request = Rack::Request.new env
        return_url = WebUserAuthorizer.handle_auth_callback_deferred request
        if return_url
          [REDIR_STATUS, { LOCATION_HEADER => return_url }, []]
        else
          [ERROR_STATUS, {}, ["No return URL is present in the request."]]
        end
      end

      def call env
        self.class.call env
      end
    end
  end
end
end

3 POD Errors

The following errors were encountered while parsing the POD:

Around line 102:

=pod directives shouldn't be over one line long! Ignoring all 6 lines of content

Around line 128:

=pod directives shouldn't be over one line long! Ignoring all 4 lines of content

Around line 150:

=pod directives shouldn't be over one line long! Ignoring all 14 lines of content