Class: Whoosh::Auth::OAuth2

Inherits:
Object
  • Object
show all
Defined in:
lib/whoosh/auth/oauth2.rb

Constant Summary collapse

PROVIDERS =
{
  google: {
    authorize_url: "https://accounts.google.com/o/oauth2/v2/auth",
    token_url: "https://oauth2.googleapis.com/token",
    userinfo_url: "https://www.googleapis.com/oauth2/v3/userinfo"
  },
  github: {
    authorize_url: "https://github.com/login/oauth/authorize",
    token_url: "https://github.com/login/oauth/access_token",
    userinfo_url: "https://api.github.com/user"
  },
  apple: {
    authorize_url: "https://appleid.apple.com/auth/authorize",
    token_url: "https://appleid.apple.com/auth/token",
    userinfo_url: nil
  }
}.freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(provider: :custom, client_id: nil, client_secret: nil, authorize_url: nil, token_url: nil, userinfo_url: nil, redirect_uri: nil, scopes: [], validator: nil) ⇒ OAuth2

Returns a new instance of OAuth2.



28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/whoosh/auth/oauth2.rb', line 28

def initialize(provider: :custom, client_id: nil, client_secret: nil,
               authorize_url: nil, token_url: nil, userinfo_url: nil,
               redirect_uri: nil, scopes: [], validator: nil)
  @provider = provider
  @client_id = client_id
  @client_secret = client_secret
  @authorize_url = authorize_url
  @token_url = token_url
  @userinfo_url = userinfo_url
  @redirect_uri = redirect_uri
  @scopes = scopes
  @validator = validator
  apply_provider_defaults if PROVIDERS[@provider]
end

Instance Attribute Details

#providerObject (readonly)

Returns the value of attribute provider.



26
27
28
# File 'lib/whoosh/auth/oauth2.rb', line 26

def provider
  @provider
end

Instance Method Details

#authenticate(request) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/whoosh/auth/oauth2.rb', line 69

def authenticate(request)
  auth_header = request.headers["Authorization"]
  raise Errors::UnauthorizedError, "Missing authorization" unless auth_header
  token = auth_header.sub(/\ABearer\s+/i, "")
  raise Errors::UnauthorizedError, "Missing token" if token.empty?

  if @validator
    result = @validator.call(token)
    raise Errors::UnauthorizedError, "Invalid token" unless result
    result
  elsif @userinfo_url
    userinfo(token)
  else
    { token: token }
  end
end

#authorize_url(state: SecureRandom.hex(16)) ⇒ Object



43
44
45
46
47
48
49
# File 'lib/whoosh/auth/oauth2.rb', line 43

def authorize_url(state: SecureRandom.hex(16))
  params = {
    client_id: @client_id, redirect_uri: @redirect_uri,
    response_type: "code", scope: @scopes.join(" "), state: state
  }
  "#{@authorize_url}?#{URI.encode_www_form(params)}"
end

#exchange_code(code) ⇒ Object



51
52
53
54
55
56
57
58
# File 'lib/whoosh/auth/oauth2.rb', line 51

def exchange_code(code)
  response = HTTP.post(@token_url, json: {
    client_id: @client_id, client_secret: @client_secret,
    code: code, redirect_uri: @redirect_uri, grant_type: "authorization_code"
  }, headers: { "Accept" => "application/json" })
  raise Errors::UnauthorizedError, "Token exchange failed: #{response.status}" unless response.ok?
  response.json
end

#userinfo(access_token) ⇒ Object



60
61
62
63
64
65
66
67
# File 'lib/whoosh/auth/oauth2.rb', line 60

def userinfo(access_token)
  return nil unless @userinfo_url
  response = HTTP.get(@userinfo_url, headers: {
    "Authorization" => "Bearer #{access_token}", "Accept" => "application/json"
  })
  raise Errors::UnauthorizedError, "Userinfo failed" unless response.ok?
  response.json
end