vamsii777 / vapor-oauth

OAuth2 Provider Library for Vapor
MIT License
3 stars 2 forks source link

Nonce Parameter Empty When Generating ID Token #8

Closed vamsii777 closed 8 months ago

vamsii777 commented 8 months ago

When generating an ID token in the OAuth flow, the nonce parameter is found to be empty. This issue occurs during the token generation process where the nonce, expected to be part of the request, is not being captured or passed correctly, resulting in an empty value when it is required for the ID token generation.

This behavior is inconsistent with the expected functionality, where the nonce should be correctly extracted from the request and utilized in the ID token creation. It’s crucial for maintaining the integrity and security of the OpenID Connect implementation.

Steps to Reproduce:

1.  Initiate the OAuth flow with a request that includes the nonce parameter.
2.  Proceed to the point of ID token generation.
3.  Observe that the nonce parameter is empty or not correctly passed.

Expected Behavior: The nonce parameter should be properly extracted from the request and available during the ID token generation process.

This issue requires investigation and resolution to ensure compliance with OpenID Connect standards and the correct functioning of the OAuth flow.

mynona commented 8 months ago

Hi @vamsii777 , I went through the whole flow with breakpoints and I observed that the nonce parameter is correctly captured.

Therefore, I looked at the code again and – hopefully / maybe – I found the issue:

The Tokens are generated via the handleToken controller. This controller calls the codeManager

guard let code = try await codeManager.getCode(codeString)

But the codeManager has no knowledge about the nonce parameter. When the code is generated the nonce parameter is not passed as parameter but in the tokenHandler the nonce parameter is taken from the code.

Token Manager:

guard let code = try await codeManager.getCode(codeString), ...
if isOpenIDConnectFlow {
            let (access, refresh, idToken) = try await tokenManager.generateTokens(
                clientID: clientID,
                userID: code.userID,
                scopes: scopes,
                accessTokenExpiryTime: expiryTime,
                idTokenExpiryTime: expiryTime,
                nonce: code.nonce
            )

But this is not possible because the CodeManager has no knowledge about nonce:

   /// Generate Authorization Code
   func generateCode(userID: String, clientID: String, redirectURI: String, scopes: [String]?, codeChallenge: String?, codeChallengeMethod: String?) throws -> String {

If this function is extended to have nonce as optional Parameter as well, then nonce can be stored when the Authorization code is generated and returned in exchange for the code.

I hope this is of some help. As I checked only the Authorization Grant Flow maybe this does not capture all situations.


If I fake it:

  /// Generate Authorization Code
   func generateCode(userID: String, clientID: String, redirectURI: String, scopes: [String]?, codeChallenge: String?, codeChallengeMethod: String?) throws -> String {

      let generatedCode = UUID().uuidString
      let expiryDate = Date().addingTimeInterval(60)

      let authorizationCode = MyAuthorizationCode(
         code_id: generatedCode,
         client_id: clientID,
         redirect_uri: redirectURI,
         user_id: userID,
         expiry_date: expiryDate,
         scopes: scopes,
         code_challenge: codeChallenge,
         code_challenge_method: codeChallengeMethod,
         nonce: "test" // FAKE IT FOR TESTING PURPOSES
      )

      _ = authorizationCode.save(on: app.db)

      return generatedCode
   }

I get the IDToken with nonce:

Bildschirmfoto 2024-01-06 um 08 36 40