]> Piment Noir Git Repositories - e-mobility-charging-stations-simulator.git/commitdiff
fix(auth): trigger post-authorize by default when DisablePostAuthorize not configured
authorJérôme Benoit <jerome.benoit@sap.com>
Tue, 31 Mar 2026 20:32:02 +0000 (22:32 +0200)
committerJérôme Benoit <jerome.benoit@sap.com>
Tue, 31 Mar 2026 20:32:02 +0000 (22:32 +0200)
Change shouldTriggerPostAuthorize from === false to !== true so that
non-Accepted local/cached tokens correctly trigger remote re-auth
when disablePostAuthorize is undefined (not configured). Previously,
undefined === false evaluated to false, silently skipping re-auth.

Also flatten redundant double try/catch in OCPP20AuthAdapter.

src/charging-station/ocpp/auth/adapters/OCPP20AuthAdapter.ts
src/charging-station/ocpp/auth/strategies/LocalAuthStrategy.ts
tests/charging-station/ocpp/auth/strategies/LocalAuthStrategy-DisablePostAuthorize.test.ts

index 9be272bba92b4b19512fd21377a2501d68090035..ef4ffabce280792b16e51481489f96afb50dc7bf 100644 (file)
@@ -68,7 +68,6 @@ export class OCPP20AuthAdapter implements OCPPAuthAdapter<OCPP20IdTokenType> {
         `${this.chargingStation.logPrefix()} ${moduleName}.${methodName}: Authorizing identifier ${truncateId(identifier.value)} via OCPP 2.0 Authorize`
       )
 
-      // Check if remote authorization is configured
       const isRemoteAuth = this.isRemoteAvailable()
       if (!isRemoteAuth) {
         return {
@@ -84,72 +83,14 @@ export class OCPP20AuthAdapter implements OCPPAuthAdapter<OCPP20IdTokenType> {
         }
       }
 
-      try {
-        const idToken = this.convertFromIdentifier(identifier)
-
-        // Validate token format
-        const isValidToken = this.isValidIdentifier(identifier)
-        if (!isValidToken) {
-          return {
-            additionalInfo: {
-              connectorId,
-              error: 'Invalid token format for OCPP 2.0',
-              transactionId,
-            },
-            isOffline: false,
-            method: AuthenticationMethod.REMOTE_AUTHORIZATION,
-            status: AuthorizationStatus.INVALID,
-            timestamp: new Date(),
-          }
-        }
-
-        logger.debug(
-          `${this.chargingStation.logPrefix()} ${moduleName}.${methodName}: Sending Authorize request (idToken: ${idToken.idToken})`
-        )
-
-        // Send Authorize request
-        const response = await this.chargingStation.ocppRequestService.requestHandler<
-          OCPP20AuthorizeRequest,
-          OCPP20AuthorizeResponse
-        >(this.chargingStation, OCPP20RequestCommand.AUTHORIZE, {
-          idToken,
-        })
-
-        // Extract authorization status from response
-        const authStatus = response.idTokenInfo.status
-        const cacheExpiryDateTime = response.idTokenInfo.cacheExpiryDateTime
-
-        // Map OCPP 2.0 authorization status
-        const mappedStatus = mapOCPP20AuthorizationStatus(authStatus)
-
-        logger.debug(
-          `${this.chargingStation.logPrefix()} ${moduleName}.${methodName}: Authorization result for ${idToken.idToken}: ${authStatus} (mapped: ${mappedStatus})`
-        )
-
-        return {
-          additionalInfo: {
-            cacheExpiryDateTime,
-            chargingPriority: response.idTokenInfo.chargingPriority,
-            connectorId,
-            ocpp20Status: authStatus,
-            tokenType: idToken.type,
-            tokenValue: idToken.idToken,
-          },
-          isOffline: false,
-          method: AuthenticationMethod.REMOTE_AUTHORIZATION,
-          status: mappedStatus,
-          timestamp: new Date(),
-        }
-      } catch (error) {
-        logger.error(
-          `${this.chargingStation.logPrefix()} ${moduleName}.${methodName}: Authorize request failed`,
-          error
-        )
+      const idToken = this.convertFromIdentifier(identifier)
 
+      const isValidToken = this.isValidIdentifier(identifier)
+      if (!isValidToken) {
         return {
           additionalInfo: {
             connectorId,
-            error: error instanceof Error ? error.message : 'Unknown error',
+            error: 'Invalid token format for OCPP 2.0',
             transactionId,
           },
           isOffline: false,
@@ -158,6 +99,41 @@ export class OCPP20AuthAdapter implements OCPPAuthAdapter<OCPP20IdTokenType> {
           timestamp: new Date(),
         }
       }
+
+      logger.debug(
+        `${this.chargingStation.logPrefix()} ${moduleName}.${methodName}: Sending Authorize request (idToken: ${idToken.idToken})`
+      )
+
+      const response = await this.chargingStation.ocppRequestService.requestHandler<
+        OCPP20AuthorizeRequest,
+        OCPP20AuthorizeResponse
+      >(this.chargingStation, OCPP20RequestCommand.AUTHORIZE, {
+        idToken,
+      })
+
+      const authStatus = response.idTokenInfo.status
+      const cacheExpiryDateTime = response.idTokenInfo.cacheExpiryDateTime
+
+      const mappedStatus = mapOCPP20AuthorizationStatus(authStatus)
+
+      logger.debug(
+        `${this.chargingStation.logPrefix()} ${moduleName}.${methodName}: Authorization result for ${idToken.idToken}: ${authStatus} (mapped: ${mappedStatus})`
+      )
+
+      return {
+        additionalInfo: {
+          cacheExpiryDateTime,
+          chargingPriority: response.idTokenInfo.chargingPriority,
+          connectorId,
+          ocpp20Status: authStatus,
+          tokenType: idToken.type,
+          tokenValue: idToken.idToken,
+        },
+        isOffline: false,
+        method: AuthenticationMethod.REMOTE_AUTHORIZATION,
+        status: mappedStatus,
+        timestamp: new Date(),
+      }
     } catch (error) {
       logger.error(
         `${this.chargingStation.logPrefix()} ${moduleName}.${methodName}: Remote authorization failed`,
index 84741033408560c337215a24f61f89bb68fae578..b6f97b8712bf3c950f08f70b2b6b5b68ae43604d 100644 (file)
@@ -516,6 +516,6 @@ export class LocalAuthStrategy implements AuthStrategy {
     result: AuthorizationResult,
     config: AuthConfiguration
   ): boolean {
-    return result.status !== AuthorizationStatus.ACCEPTED && config.disablePostAuthorize === false
+    return result.status !== AuthorizationStatus.ACCEPTED && config.disablePostAuthorize !== true
   }
 }
index ccef7f8c6f38bdeb974765fe25b6b97cd5dc4e00..d942a091541c5fd942aee40fdf16630b6b59880f 100644 (file)
@@ -114,7 +114,7 @@ await describe('LocalAuthStrategy - DisablePostAuthorize', async () => {
   })
 
   await describe('default behavior', async () => {
-    await it('should be no-op when DisablePostAuthorize not configured (default behavior preserved)', async () => {
+    await it('should trigger re-auth when DisablePostAuthorize not configured (defaults to enabled)', async () => {
       // Arrange
       const blockedResult = createMockAuthorizationResult({
         method: AuthenticationMethod.CACHE,
@@ -135,9 +135,8 @@ await describe('LocalAuthStrategy - DisablePostAuthorize', async () => {
       // Act
       const result = await strategy.authenticate(request, config)
 
-      // Assert - returns cached result as-is (disablePostAuthorize not in config)
-      assert.notStrictEqual(result, undefined)
-      assert.strictEqual(result?.status, AuthorizationStatus.BLOCKED)
+      // Assert - undefined signals orchestrator should try remote strategy (C10.FR.03)
+      assert.strictEqual(result, undefined)
     })
   })
 })