File: id_tokens.rb

package info (click to toggle)
ruby-googleauth 1.3.0-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 284 kB
  • sloc: ruby: 1,517; makefile: 4
file content (219 lines) | stat: -rw-r--r-- 8,764 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
# frozen_string_literal: true

# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

require "googleauth/id_tokens/errors"
require "googleauth/id_tokens/key_sources"
require "googleauth/id_tokens/verifier"

module Google
  module Auth
    ##
    # ## Verifying Google ID tokens
    #
    # This module verifies ID tokens issued by Google. This can be used to
    # authenticate signed-in users using OpenID Connect. See
    # https://developers.google.com/identity/sign-in/web/backend-auth for more
    # information.
    #
    # ### Basic usage
    #
    # To verify an ID token issued by Google accounts:
    #
    #     payload = Google::Auth::IDTokens.verify_oidc the_token,
    #                                                  aud: "my-app-client-id"
    #
    # If verification succeeds, you will receive the token's payload as a hash.
    # If verification fails, an exception (normally a subclass of
    # {Google::Auth::IDTokens::VerificationError}) will be raised.
    #
    # To verify an ID token issued by the Google identity-aware proxy (IAP):
    #
    #     payload = Google::Auth::IDTokens.verify_iap the_token,
    #                                                 aud: "my-app-client-id"
    #
    # These methods will automatically download and cache the Google public
    # keys necessary to verify these tokens. They will also automatically
    # verify the issuer (`iss`) field for their respective types of ID tokens.
    #
    # ### Advanced usage
    #
    # If you want to provide your own public keys, either by pointing at a
    # custom URI or by providing the key data directly, use the Verifier class
    # and pass in a key source.
    #
    # To point to a custom URI that returns a JWK set:
    #
    #     source = Google::Auth::IDTokens::JwkHttpKeySource.new "https://example.com/jwk"
    #     verifier = Google::Auth::IDTokens::Verifier.new key_source: source
    #     payload = verifier.verify the_token, aud: "my-app-client-id"
    #
    # To provide key data directly:
    #
    #     jwk_data = {
    #       keys: [
    #         {
    #           alg: "ES256",
    #           crv: "P-256",
    #           kid: "LYyP2g",
    #           kty: "EC",
    #           use: "sig",
    #           x: "SlXFFkJ3JxMsXyXNrqzE3ozl_0913PmNbccLLWfeQFU",
    #           y: "GLSahrZfBErmMUcHP0MGaeVnJdBwquhrhQ8eP05NfCI"
    #         }
    #       ]
    #     }
    #     source = Google::Auth::IDTokens::StaticKeySource.from_jwk_set jwk_data
    #     verifier = Google::Auth::IDTokens::Verifier key_source: source
    #     payload = verifier.verify the_token, aud: "my-app-client-id"
    #
    module IDTokens
      ##
      # A list of issuers expected for Google OIDC-issued tokens.
      #
      # @return [Array<String>]
      #
      OIDC_ISSUERS = ["accounts.google.com", "https://accounts.google.com"].freeze

      ##
      # A list of issuers expected for Google IAP-issued tokens.
      #
      # @return [Array<String>]
      #
      IAP_ISSUERS = ["https://cloud.google.com/iap"].freeze

      ##
      # The URL for Google OAuth2 V3 public certs
      #
      # @return [String]
      #
      OAUTH2_V3_CERTS_URL = "https://www.googleapis.com/oauth2/v3/certs"

      ##
      # The URL for Google IAP public keys
      #
      # @return [String]
      #
      IAP_JWK_URL = "https://www.gstatic.com/iap/verify/public_key-jwk"

      class << self
        ##
        # The key source providing public keys that can be used to verify
        # ID tokens issued by Google OIDC.
        #
        # @return [Google::Auth::IDTokens::JwkHttpKeySource]
        #
        def oidc_key_source
          @oidc_key_source ||= JwkHttpKeySource.new OAUTH2_V3_CERTS_URL
        end

        ##
        # The key source providing public keys that can be used to verify
        # ID tokens issued by Google IAP.
        #
        # @return [Google::Auth::IDTokens::JwkHttpKeySource]
        #
        def iap_key_source
          @iap_key_source ||= JwkHttpKeySource.new IAP_JWK_URL
        end

        ##
        # Reset all convenience key sources. Used for testing.
        # @private
        #
        def forget_sources!
          @oidc_key_source = @iap_key_source = nil
          self
        end

        ##
        # A convenience method that verifies a token allegedly issued by Google
        # OIDC.
        #
        # @param token [String] The ID token to verify
        # @param aud [String,Array<String>,nil] The expected audience. At least
        #     one `aud` field in the token must match at least one of the
        #     provided audiences, or the verification will fail with
        #     {Google::Auth::IDToken::AudienceMismatchError}. If `nil` (the
        #     default), no audience checking is performed.
        # @param azp [String,Array<String>,nil] The expected authorized party
        #     (azp). At least one `azp` field in the token must match at least
        #     one of the provided values, or the verification will fail with
        #     {Google::Auth::IDToken::AuthorizedPartyMismatchError}. If `nil`
        #     (the default), no azp checking is performed.
        # @param aud [String,Array<String>,nil] The expected audience. At least
        #     one `iss` field in the token must match at least one of the
        #     provided issuers, or the verification will fail with
        #     {Google::Auth::IDToken::IssuerMismatchError}. If `nil`, no issuer
        #     checking is performed. Default is to check against {OIDC_ISSUERS}.
        #
        # @return [Hash] The decoded token payload.
        # @raise [KeySourceError] if the key source failed to obtain public keys
        # @raise [VerificationError] if the token verification failed.
        #     Additional data may be available in the error subclass and message.
        #
        def verify_oidc token,
                        aud: nil,
                        azp: nil,
                        iss: OIDC_ISSUERS

          verifier = Verifier.new key_source: oidc_key_source,
                                  aud:        aud,
                                  azp:        azp,
                                  iss:        iss
          verifier.verify token
        end

        ##
        # A convenience method that verifies a token allegedly issued by Google
        # IAP.
        #
        # @param token [String] The ID token to verify
        # @param aud [String,Array<String>,nil] The expected audience. At least
        #     one `aud` field in the token must match at least one of the
        #     provided audiences, or the verification will fail with
        #     {Google::Auth::IDToken::AudienceMismatchError}. If `nil` (the
        #     default), no audience checking is performed.
        # @param azp [String,Array<String>,nil] The expected authorized party
        #     (azp). At least one `azp` field in the token must match at least
        #     one of the provided values, or the verification will fail with
        #     {Google::Auth::IDToken::AuthorizedPartyMismatchError}. If `nil`
        #     (the default), no azp checking is performed.
        # @param aud [String,Array<String>,nil] The expected audience. At least
        #     one `iss` field in the token must match at least one of the
        #     provided issuers, or the verification will fail with
        #     {Google::Auth::IDToken::IssuerMismatchError}. If `nil`, no issuer
        #     checking is performed. Default is to check against {IAP_ISSUERS}.
        #
        # @return [Hash] The decoded token payload.
        # @raise [KeySourceError] if the key source failed to obtain public keys
        # @raise [VerificationError] if the token verification failed.
        #     Additional data may be available in the error subclass and message.
        #
        def verify_iap token,
                       aud: nil,
                       azp: nil,
                       iss: IAP_ISSUERS

          verifier = Verifier.new key_source: iap_key_source,
                                  aud:        aud,
                                  azp:        azp,
                                  iss:        iss
          verifier.verify token
        end
      end
    end
  end
end