@@ -121,14 +121,80 @@ func (o *Oauth2idc) CodeUrl2(state string) string {
121121}
122122
123123// Exchange exchange code for Oauth2 token
124- func (o * Oauth2idc ) Exchange (code string ) (* oauth2.Token , error ) {
124+ func (o * Oauth2idc ) Exchange (auth model.Auth ) (* oauth2.Token , error ) {
125+
126+ if auth .Connection == "apple" {
127+ // Make a http request using the agent configuration information
128+ client_id := os .Getenv ("OAUTH2_AGENT_CLIENT_ID" )
129+ client_secret := os .Getenv ("OAUTH2_AGENT_CLIENT_SECRET" )
130+ redirect_url := os .Getenv ("OAUTH2_AGENT_REDIRECT_URL" )
131+ audience := os .Getenv ("OAUTH2_AGENT_AUDIENCE" )
132+
133+ provider := os .Getenv ("OAUTH2_AGENT_PROVIDER" )
134+
135+ // make an http post to the oauth2 token endpoint
136+ // with the code and other required parameters
137+ // to get the access token
138+ // and other information
139+
140+ httpClient := & http.Client {
141+ Transport : & CustomTransport {
142+ Transport : http .DefaultTransport ,
143+ UserAgent : "nettica-admin/2.0" ,
144+ },
145+ }
146+ rsp , err := httpClient .PostForm (provider + "oauth/token/" , url.Values {
147+ "grant_type" : {"urn:ietf:params:oauth:grant-type:token-exchange" },
148+ "client_id" : {client_id },
149+ "client_secret" : {client_secret },
150+ "redirect_uri" : {redirect_url },
151+ "audience" : {audience },
152+ "subject_token" : {auth .Code },
153+ "subject_token_type" : {"http://auth0.com/oauth/token-type/apple-authz-code" },
154+ })
155+ if err != nil {
156+ log .Info (err )
157+ return nil , err
158+ }
159+ defer rsp .Body .Close ()
125160
126- oauth2Token , err := oauth2Config .Exchange (ctx , code )
127- if err != nil {
128- return nil , err
161+ body , err := io .ReadAll (rsp .Body )
162+ if err != nil {
163+ log .Info (err )
164+ return nil , err
165+ }
166+ log .Infof ("body: %s" , body )
167+
168+ // read the response body and serialize it into a TokenResponse struct
169+ var tokenResponse TokenResponse
170+
171+ // decode the body bytes into the struct
172+
173+ err = json .Unmarshal (body , & tokenResponse )
174+ if err != nil {
175+ log .Info (err )
176+ return nil , err
177+ }
178+
179+ oauth2Token := & oauth2.Token {
180+ AccessToken : tokenResponse .AccessToken ,
181+ Expiry : time .Now ().Add (time .Duration (tokenResponse .ExpiresIn ) * time .Second ),
182+ TokenType : tokenResponse .TokenType ,
183+ }
184+ oauth2Token = oauth2Token .WithExtra (map [string ]interface {}{ // Add the ID token to the extra parameters
185+ "id_token" : auth .IdToken })
186+
187+ return oauth2Token , nil
188+
189+ } else {
190+ oauth2Token , err := oauth2Config .Exchange (ctx , auth .Code )
191+ if err != nil {
192+ return nil , err
193+ }
194+ return oauth2Token , nil
129195 }
130196
131- return oauth2Token , nil
197+ return nil , nil
132198}
133199func (o * Oauth2idc ) Exchange2 (code string ) (* oauth2.Token , error ) {
134200
@@ -199,6 +265,29 @@ func (o *Oauth2idc) Exchange2(code string) (*oauth2.Token, error) {
199265 return oauth2Token , nil
200266}
201267
268+ func verifyAppleIDToken (ctx context.Context , tokenString string ) (* oidc.IDToken , error ) {
269+ // Apple's OIDC discovery URL
270+ provider , err := oidc .NewProvider (ctx , "https://appleid.apple.com" )
271+ if err != nil {
272+ return nil , fmt .Errorf ("failed to get Apple OIDC provider: %v" , err )
273+ }
274+
275+ // Set up an ID Token verifier using the provider and your client ID
276+ verifier := provider .Verifier (& oidc.Config {ClientID : "com.nettica.agent" })
277+ if verifier == nil {
278+ return nil , fmt .Errorf ("failed to create verifier" )
279+ }
280+
281+ // Verify and parse ID Token
282+ idToken , err := verifier .Verify (ctx , tokenString )
283+ if err != nil {
284+ return nil , fmt .Errorf ("ID Token verification failed: %v" , err )
285+ }
286+
287+ // Successfully verified ID Token
288+ return idToken , nil
289+ }
290+
202291// UserInfo get token user
203292func (o * Oauth2idc ) UserInfo (oauth2Token * oauth2.Token ) (* model.User , error ) {
204293 rawIDToken , ok := oauth2Token .Extra ("id_token" ).(string )
@@ -208,7 +297,10 @@ func (o *Oauth2idc) UserInfo(oauth2Token *oauth2.Token) (*model.User, error) {
208297
209298 verified := false
210299 var idToken * oidc.IDToken
300+ var userInfo * oidc.UserInfo
211301 var err error
302+ // ID Token payload is just JSON
303+ var claims map [string ]interface {}
212304
213305 for _ , verifier := range oidcIDTokenVerifier {
214306 idToken , err = verifier .Verify (ctx , rawIDToken )
@@ -218,6 +310,21 @@ func (o *Oauth2idc) UserInfo(oauth2Token *oauth2.Token) (*model.User, error) {
218310 }
219311 }
220312
313+ if ! verified {
314+ idToken , err = verifyAppleIDToken (ctx , rawIDToken )
315+ if err == nil {
316+ verified = true
317+ }
318+
319+ // get the user info from the id token
320+ idToken .Claims (& claims )
321+ userInfo = & oidc.UserInfo {
322+ Subject : "apple|" + idToken .Subject ,
323+ Email : claims ["email" ].(string ),
324+ }
325+ // add the claims to the user info
326+ }
327+
221328 if ! verified || err != nil {
222329 return nil , err
223330 }
@@ -227,15 +334,16 @@ func (o *Oauth2idc) UserInfo(oauth2Token *oauth2.Token) (*model.User, error) {
227334 return cacheUser .(* model.User ), nil
228335 }
229336
230- userInfo , err := oidcProvider .UserInfo (ctx , oauth2 .StaticTokenSource (oauth2Token ))
231- if err != nil {
232- return nil , err
233- }
337+ if userInfo == nil {
338+ userInfo , err = oidcProvider .UserInfo (ctx , oauth2 .StaticTokenSource (oauth2Token ))
339+ if err != nil {
340+ return nil , err
341+ }
342+
343+ if err := userInfo .Claims (& claims ); err != nil {
344+ return nil , fmt .Errorf ("failed to get id token claims: %s" , err )
345+ }
234346
235- // ID Token payload is just JSON
236- var claims map [string ]interface {}
237- if err := userInfo .Claims (& claims ); err != nil {
238- return nil , fmt .Errorf ("failed to get id token claims: %s" , err )
239347 }
240348
241349 // get some infos about user
0 commit comments