@@ -10,15 +10,17 @@ public protocol OpenGoogleSignInDelegate: AnyObject {
1010
1111/// Signs the user in with Google using OAuth 2.0.
1212public final class OpenGoogleSignIn : NSObject {
13-
13+
1414 // MARK: - Public properties
15-
15+
1616 public weak var delegate : OpenGoogleSignInDelegate ?
1717
1818 /// The client ID of the app.
1919 /// It is required for communication with Google API to work.
2020 public var clientID : String = " "
2121
22+ public var audience : String ?
23+
2224 /// Client secret.
2325 /// It is only used when exchanging the authorization code for an access token.
2426 public var clientSecret : String = " "
@@ -35,15 +37,15 @@ public final class OpenGoogleSignIn: NSObject {
3537 /// View controller to present Google sign-in flow.
3638 /// Needs to be set for presenting to work correctly.
3739 public weak var presentingViewController : UIViewController ? = nil
38-
40+
3941 // MARK: - Private properties
4042
4143 /// Session used to authenticate a user with Google sign-in.
4244 private var authenticationSession : ASWebAuthenticationSession ? = nil
43-
45+
4446 /// Google API OAuth 2.0 token url.
4547 private static let tokenURL : URL ? = URL ( string: " https://www.googleapis.com/oauth2/v4/token " )
46-
48+
4749 /// Google API profile url
4850 private static let profileURL : URL ? = URL ( string: " https://www.googleapis.com/oauth2/v1/userinfo?alt=json " )
4951
@@ -56,33 +58,32 @@ public final class OpenGoogleSignIn: NSObject {
5658 . joined ( separator: " . " )
5759 ) + " :/oauth2redirect/google "
5860 }
59-
61+
6062 /// Authorization `URL` based on parameters provided by the app.
6163 private var authURL : URL {
6264 let scopes = scopes. map { $0. rawValue } . joined ( separator: " + " )
6365 var components = URLComponents ( )
64-
66+
6567 components. scheme = " https "
6668 components. host = " accounts.google.com "
6769 components. path = " /o/oauth2/v2/auth "
68-
70+
6971 components. queryItems = [
7072 URLQueryItem ( name: " client_id " , value: clientID) ,
7173 URLQueryItem ( name: " redirect_uri " , value: redirectURI) ,
7274 URLQueryItem ( name: " response_type " , value: " code " ) ,
73- URLQueryItem ( name: " scope " , value: scopes)
75+ URLQueryItem ( name: " scope " , value: scopes) ,
7476 ]
7577
7678 return components. url!
7779 }
78-
80+
7981 // MARK: - Initialization
80-
82+
8183 private override init ( ) { }
82-
84+
8385 // MARK: - Public helpers
84-
85-
86+
8687 /// Handles token response.
8788 /// Calls `OpenGoogleSignInDelegate` with valid response or error.
8889 public func handle( _ url: URL ) {
@@ -125,23 +126,23 @@ public final class OpenGoogleSignIn: NSObject {
125126 self ? . handle ( callbackURL)
126127 }
127128 }
128-
129+
129130 // Set `presentationContextProvider` for iOS 13+ modals to work correctly
130131 if #available( iOS 13 . 0 , * ) {
131132 authenticationSession? . presentationContextProvider = self
132133 }
133-
134+
134135 // Start authentication session
135136 authenticationSession? . start ( )
136137 }
137-
138+
138139 // MARK: - Private helpers
139140
140141 /// Decodes `GoogleUser` from OAuth 2.0 response.
141142 private func decodeUser( from data: Data ) throws -> GoogleUser {
142143 try JSONDecoder . app. decode ( GoogleUser . self, from: data)
143144 }
144-
145+
145146 /// Handles OAuth 2.0 token response.
146147 ///
147148 /// After successful authentication we made another request
@@ -151,12 +152,12 @@ public final class OpenGoogleSignIn: NSObject {
151152 completion ( . failure( . invalidCode) )
152153 return
153154 }
154-
155+
155156 guard let tokenRequest = makeTokenRequest ( with: code) else {
156157 assertionFailure ( " Invalid token request " )
157158 return
158159 }
159-
160+
160161 makeRequest ( tokenRequest) { result in
161162 switch result {
162163 case let . success( data) :
@@ -166,7 +167,7 @@ public final class OpenGoogleSignIn: NSObject {
166167 } catch {
167168 completion ( . failure( . tokenDecodingError( error) ) )
168169 }
169-
170+
170171 case let . failure( error) :
171172 completion ( . failure( error) )
172173 }
@@ -178,9 +179,9 @@ public final class OpenGoogleSignIn: NSObject {
178179 assertionFailure ( " Invalid profile request " )
179180 return
180181 }
181-
182+
182183 var user = user
183-
184+
184185 makeRequest ( profileRequest) { result in
185186 switch result {
186187 case let . success( data) :
@@ -193,15 +194,15 @@ public final class OpenGoogleSignIn: NSObject {
193194 }
194195 }
195196 }
196-
197+
197198 /// Wrapper for easier `URLRequest` handling.
198199 private func makeRequest( _ request: URLRequest , completion: @escaping ( Result < Data , GoogleSignInError > ) -> Void ) {
199- let task = session. dataTask ( with: request) { data, response , error in
200+ let task = session. dataTask ( with: request) { data, _ , error in
200201 if let error = error {
201202 completion ( . failure( . networkError( error) ) )
202203 return
203204 }
204-
205+
205206 guard let data = data else {
206207 completion ( . failure( . invalidResponse) )
207208 return
@@ -222,35 +223,38 @@ public final class OpenGoogleSignIn: NSObject {
222223 /// Returns `URLRequest` to retrieve Google sign-in OAuth 2.0 token using arameters provided by the app.
223224 func makeTokenRequest( with code: String ) -> URLRequest ? {
224225 guard let tokenURL = OpenGoogleSignIn . tokenURL else { return nil }
225-
226+
226227 var request = URLRequest ( url: tokenURL)
227228 request. httpMethod = " POST "
228229 request. setValue ( " application/x-www-form-urlencoded " , forHTTPHeaderField: " Content-Type " )
229-
230- let parameters = [
230+
231+ var parameters = [
231232 " client_id " : clientID,
232233 " client_secret " : clientSecret,
233234 " code " : code,
234235 " grant_type " : " authorization_code " ,
235236 " redirect_uri " : redirectURI
236237 ]
237-
238+ if let audience = audience {
239+ parameters [ " audience " ] = audience
240+ }
241+
238242 let body = parameters
239243 . map { " \( $0) = \( $1) " }
240244 . joined ( separator: " & " )
241-
245+
242246 request. httpBody = body. data ( using: . utf8)
243247
244248 return request
245249 }
246-
250+
247251 /// Returns `URLRequest` to retrieve user's profile data
248252 func makeProfileRequest( user: GoogleUser ) -> URLRequest ? {
249253 guard let profileURL = OpenGoogleSignIn . profileURL else { return nil }
250-
254+
251255 var request = URLRequest ( url: profileURL)
252256 request. setValue ( " Bearer " + user. accessToken, forHTTPHeaderField: " Authorization " )
253-
257+
254258 return request
255259 }
256260}
0 commit comments