connectorId,
context: AuthContext.TRANSACTION_START,
identifier: {
- ocppVersion: stationOcppVersion,
type: IdentifierType.ID_TAG,
value: idTag,
},
* Convert OCPP 1.6 idTag to unified identifier
* @param identifier - OCPP 1.6 idTag string to convert
* @param additionalData - Optional metadata to include in unified identifier
- * @returns Unified identifier with ID_TAG type and OCPP 1.6 version
+ * @returns Unified identifier with ID_TAG type
*/
convertToUnifiedIdentifier (
identifier: string,
additionalInfo: additionalData
? Object.fromEntries(Object.entries(additionalData).map(([k, v]) => [k, String(v)]))
: undefined,
- ocppVersion: OCPPVersion.VERSION_16,
parentId: additionalData?.parentId as string | undefined,
type: IdentifierType.ID_TAG,
value: identifier,
* Convert OCPP 2.0 IdToken to unified identifier
* @param identifier - OCPP 2.0 IdToken or raw string identifier
* @param additionalData - Optional metadata to include in the unified identifier
- * @returns Unified identifier with normalized type and OCPP version metadata
+ * @returns Unified identifier with normalized type and metadata
*/
convertToUnifiedIdentifier (
identifier: OCPP20IdTokenType | string,
? Object.fromEntries(Object.entries(additionalData).map(([k, v]) => [k, String(v)]))
: {}),
},
- ocppVersion: OCPPVersion.VERSION_20,
parentId: additionalData?.parentId as string | undefined,
type: unifiedType,
value: idToken.idToken,
const supportedTypes = new Set<string>()
// Test common identifier types
- const ocppVersion =
- this.chargingStation.stationInfo?.ocppVersion === OCPPVersion.VERSION_16
- ? OCPPVersion.VERSION_16
- : OCPPVersion.VERSION_20
const testIdentifiers: UnifiedIdentifier[] = [
- { ocppVersion, type: IdentifierType.ISO14443, value: 'test' },
- { ocppVersion, type: IdentifierType.ISO15693, value: 'test' },
- { ocppVersion, type: IdentifierType.KEY_CODE, value: 'test' },
- { ocppVersion, type: IdentifierType.LOCAL, value: 'test' },
- { ocppVersion, type: IdentifierType.MAC_ADDRESS, value: 'test' },
- { ocppVersion, type: IdentifierType.NO_AUTHORIZATION, value: 'test' },
+ { type: IdentifierType.ISO14443, value: 'test' },
+ { type: IdentifierType.ISO15693, value: 'test' },
+ { type: IdentifierType.KEY_CODE, value: 'test' },
+ { type: IdentifierType.LOCAL, value: 'test' },
+ { type: IdentifierType.MAC_ADDRESS, value: 'test' },
+ { type: IdentifierType.NO_AUTHORIZATION, value: 'test' },
]
testIdentifiers.forEach(identifier => {
const adapter = this.adapter
// For OCPP 2.0, we can use certificate-based validation
- if (request.identifier.ocppVersion === OCPPVersion.VERSION_20) {
+ if (this.adapter.ocppVersion === OCPPVersion.VERSION_20) {
const result = await this.validateCertificateWithOCPP20(request, adapter, config)
this.updateStatistics(result, startTime)
return result
// Should not reach here due to canHandle check, but handle gracefully
return this.createFailureResult(
AuthorizationStatus.INVALID,
- `Certificate authentication not supported for OCPP ${request.identifier.ocppVersion}`,
+ `Certificate authentication not supported for OCPP ${this.adapter.ocppVersion}`,
request.identifier,
startTime
)
}
// Only supported in OCPP 2.0+
- if (request.identifier.ocppVersion === OCPPVersion.VERSION_16) {
+ if (this.adapter.ocppVersion === OCPPVersion.VERSION_16) {
return false
}
/** Group identifier for group-based authorization (OCPP 2.0) */
readonly groupId?: string
- /** OCPP version this identifier originated from */
- readonly ocppVersion: OCPPVersion
-
/** Parent ID for hierarchical authorization (OCPP 1.6) */
readonly parentId?: string
const request = createMockAuthRequest({
connectorId: 1,
context: AuthContext.TRANSACTION_START,
- identifier: createMockIdentifier(OCPPVersion.VERSION_16, 'VALID_ID_123'),
+ identifier: createMockIdentifier('VALID_ID_123'),
})
const result = await authService16.authenticate(request)
const request = createMockAuthRequest({
connectorId: 1,
context,
- identifier: createMockIdentifier(OCPPVersion.VERSION_16, `CONTEXT_TEST_${context}`),
+ identifier: createMockIdentifier(`CONTEXT_TEST_${context}`),
})
const result = await authService16.authenticate(request)
await it('should authorize request directly', async () => {
const request = createMockAuthRequest({
connectorId: 1,
- identifier: createMockIdentifier(OCPPVersion.VERSION_16, 'AUTH_DIRECT_TEST'),
+ identifier: createMockIdentifier('AUTH_DIRECT_TEST'),
})
const result = await authService16.authorize(request)
const request = createMockAuthRequest({
connectorId: 2,
context: AuthContext.TRANSACTION_START,
- identifier: createMockIdentifier(OCPPVersion.VERSION_20, 'VALID_ID_456'),
+ identifier: createMockIdentifier('VALID_ID_456'),
})
const result = await authService20.authenticate(request)
const request = createMockAuthRequest({
connectorId: 2,
context,
- identifier: createMockIdentifier(OCPPVersion.VERSION_20, `V20_CONTEXT_${context}`),
+ identifier: createMockIdentifier(`V20_CONTEXT_${context}`),
})
const result = await authService20.authenticate(request)
connectorId: 999, // Invalid connector
context: AuthContext.TRANSACTION_START,
identifier: {
- ocppVersion: OCPPVersion.VERSION_16,
type: IdentifierType.ISO14443,
value: '', // Invalid empty value
},
const request = createMockAuthRequest({
connectorId: 1,
context: i % 2 === 0 ? AuthContext.TRANSACTION_START : AuthContext.TRANSACTION_STOP,
- identifier: createMockIdentifier(OCPPVersion.VERSION_16, `CONCURRENT_${String(i)}`),
+ identifier: createMockIdentifier(`CONCURRENT_${String(i)}`),
})
promises.push(authServiceConcurrent.authenticate(request))
}
strategy.initialize(config)
const request = createMockAuthRequest({
- identifier: createMockIdentifier(OCPPVersion.VERSION_16, 'LIST-ID'),
+ identifier: createMockIdentifier('LIST-ID'),
})
const result = await strategy.authenticate(request, config)
const idTag = 'TEST_ID_TAG'
const result = adapter.convertToUnifiedIdentifier(idTag)
- const expected = createMockIdentifier(OCPPVersion.VERSION_16, idTag)
+ const expected = createMockIdentifier(idTag)
assert.strictEqual(result.value, expected.value)
assert.strictEqual(result.type, expected.type)
- assert.strictEqual(result.ocppVersion, expected.ocppVersion)
})
await it('should include additional data in unified identifier', () => {
await describe('convertFromUnifiedIdentifier', async () => {
await it('should convert unified identifier to OCPP 1.6 idTag', () => {
- const identifier = createMockIdentifier(OCPPVersion.VERSION_16, 'TEST_ID_TAG')
+ const identifier = createMockIdentifier('TEST_ID_TAG')
const result = adapter.convertFromUnifiedIdentifier(identifier)
assert.strictEqual(result, 'TEST_ID_TAG')
await describe('isValidIdentifier', async () => {
await it('should validate correct OCPP 1.6 identifier', () => {
- const identifier = createMockIdentifier(OCPPVersion.VERSION_16, 'VALID_TAG')
+ const identifier = createMockIdentifier('VALID_TAG')
assert.strictEqual(adapter.isValidIdentifier(identifier), true)
})
await it('should reject identifier with empty value', () => {
- const identifier = createMockIdentifier(OCPPVersion.VERSION_16, '')
+ const identifier = createMockIdentifier('')
assert.strictEqual(adapter.isValidIdentifier(identifier), false)
})
await it('should reject identifier exceeding max length (20 chars)', () => {
- const identifier = createMockIdentifier(
- OCPPVersion.VERSION_16,
- 'THIS_TAG_IS_TOO_LONG_FOR_OCPP16'
- )
+ const identifier = createMockIdentifier('THIS_TAG_IS_TOO_LONG_FOR_OCPP16')
assert.strictEqual(adapter.isValidIdentifier(identifier), false)
})
await it('should reject non-ID_TAG types', () => {
- const identifier = createMockIdentifier(
- OCPPVersion.VERSION_16,
- 'TEST_TAG',
- IdentifierType.CENTRAL
- )
+ const identifier = createMockIdentifier('TEST_TAG', IdentifierType.CENTRAL)
assert.strictEqual(adapter.isValidIdentifier(identifier), false)
})
await describe('authorizeRemote', async () => {
await it('should perform remote authorization successfully', async () => {
- const identifier = createMockIdentifier(OCPPVersion.VERSION_16, 'VALID_TAG')
+ const identifier = createMockIdentifier('VALID_TAG')
const result = await adapter.authorizeRemote(identifier, 1, 123)
reject(new Error('Network error'))
})
- const identifier = createMockIdentifier(OCPPVersion.VERSION_16, 'TEST_TAG')
+ const identifier = createMockIdentifier('TEST_TAG')
const result = await adapter.authorizeRemote(identifier, 1)
}
const result = adapter.convertToUnifiedIdentifier(idToken)
- const expected = createMockIdentifier(OCPPVersion.VERSION_20, 'TEST_TOKEN')
+ const expected = createMockIdentifier('TEST_TOKEN')
assert.strictEqual(result.value, expected.value)
assert.strictEqual(result.type, IdentifierType.ID_TAG)
- assert.strictEqual(result.ocppVersion, expected.ocppVersion)
assert.strictEqual(result.additionalInfo?.ocpp20Type, OCPP20IdTokenEnumType.Central)
})
await it('should convert string to unified identifier', () => {
const result = adapter.convertToUnifiedIdentifier('STRING_TOKEN')
- const expected = createMockIdentifier(OCPPVersion.VERSION_20, 'STRING_TOKEN')
+ const expected = createMockIdentifier('STRING_TOKEN')
assert.strictEqual(result.value, expected.value)
assert.strictEqual(result.type, expected.type)
- assert.strictEqual(result.ocppVersion, expected.ocppVersion)
})
await it('should handle eMAID type correctly', () => {
await describe('convertFromUnifiedIdentifier', async () => {
await it('should convert unified identifier to OCPP 2.0 IdToken', () => {
- const identifier = createMockIdentifier(
- OCPPVersion.VERSION_20,
- 'CENTRAL_TOKEN',
- IdentifierType.CENTRAL
- )
+ const identifier = createMockIdentifier('CENTRAL_TOKEN', IdentifierType.CENTRAL)
const result = adapter.convertFromUnifiedIdentifier(identifier)
})
await it('should map E_MAID type correctly', () => {
- const identifier = createMockIdentifier(
- OCPPVersion.VERSION_20,
- 'EMAID_TOKEN',
- IdentifierType.E_MAID
- )
+ const identifier = createMockIdentifier('EMAID_TOKEN', IdentifierType.E_MAID)
const result = adapter.convertFromUnifiedIdentifier(identifier)
})
await it('should handle ID_TAG to Local mapping', () => {
- const identifier = createMockIdentifier(OCPPVersion.VERSION_20, 'LOCAL_TAG')
+ const identifier = createMockIdentifier('LOCAL_TAG')
const result = adapter.convertFromUnifiedIdentifier(identifier)
await describe('isValidIdentifier', async () => {
await it('should validate correct OCPP 2.0 identifier', () => {
- const identifier = createMockIdentifier(
- OCPPVersion.VERSION_20,
- 'VALID_TOKEN',
- IdentifierType.CENTRAL
- )
+ const identifier = createMockIdentifier('VALID_TOKEN', IdentifierType.CENTRAL)
assert.strictEqual(adapter.isValidIdentifier(identifier), true)
})
await it('should reject identifier with empty value', () => {
- const identifier = createMockIdentifier(OCPPVersion.VERSION_20, '', IdentifierType.CENTRAL)
+ const identifier = createMockIdentifier('', IdentifierType.CENTRAL)
assert.strictEqual(adapter.isValidIdentifier(identifier), false)
})
await it('should reject identifier exceeding max length (36 chars)', () => {
const identifier = createMockIdentifier(
- OCPPVersion.VERSION_20,
'THIS_TOKEN_IS_DEFINITELY_TOO_LONG_FOR_OCPP20_SPECIFICATION',
IdentifierType.CENTRAL
)
]
for (const type of validTypes) {
- const identifier = createMockIdentifier(OCPPVersion.VERSION_20, 'VALID_TOKEN', type)
+ const identifier = createMockIdentifier('VALID_TOKEN', type)
assert.strictEqual(adapter.isValidIdentifier(identifier), true)
}
})
),
} as unknown as ChargingStation['ocppRequestService']
- const identifier = createMockIdentifier(
- OCPPVersion.VERSION_20,
- 'VALID_TOKEN',
- IdentifierType.CENTRAL
- )
+ const identifier = createMockIdentifier('VALID_TOKEN', IdentifierType.CENTRAL)
const result = await adapter.authorizeRemote(identifier, 1, 'tx_123')
})
await it('should handle invalid token gracefully', async () => {
- const identifier = createMockIdentifier(OCPPVersion.VERSION_20, '', IdentifierType.CENTRAL)
+ const identifier = createMockIdentifier('', IdentifierType.CENTRAL)
const result = await adapter.authorizeRemote(identifier, 1)
/**
* Create a mock UnifiedIdentifier for any OCPP version.
- * @param ocppVersion - OCPP version (defaults to VERSION_16)
* @param value - Identifier token value (defaults to 'TEST-TAG-001')
* @param type - Identifier type enum value (defaults to ID_TAG)
- * @returns Mock UnifiedIdentifier configured for specified OCPP version
+ * @returns Mock UnifiedIdentifier configured for testing
*/
export const createMockIdentifier = (
- ocppVersion: OCPPVersion = OCPPVersion.VERSION_16,
value = 'TEST-TAG-001',
type: IdentifierType = IdentifierType.ID_TAG
): UnifiedIdentifier => ({
- ocppVersion,
type,
value,
})
? identifier.value
: { idToken: identifier.value, type: identifier.type },
convertToUnifiedIdentifier: (identifier: object | string) => ({
- ocppVersion,
type: IdentifierType.ID_TAG,
value:
typeof identifier === 'string'
await authService.initialize()
const idTagIdentifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_16,
type: IdentifierType.ID_TAG,
value: 'VALID_ID_TAG',
}
await authService.initialize()
const centralIdentifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_20,
type: IdentifierType.CENTRAL,
value: 'CENTRAL_ID',
}
const authService = new OCPPAuthServiceImpl(mockStation)
const identifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_16,
type: IdentifierType.ID_TAG,
value: 'TAG_TO_INVALIDATE',
}
const authService = new OCPPAuthServiceImpl(mockStation)
const identifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_16,
type: IdentifierType.ID_TAG,
value: 'VALID_TAG',
}
const authService = new OCPPAuthServiceImpl(mockStation)
const identifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_16,
type: IdentifierType.ID_TAG,
value: 'UNKNOWN_TAG',
}
const authService = new OCPPAuthServiceImpl(mockStation)
const identifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_16,
type: IdentifierType.ID_TAG,
value: 'LOCAL_TAG',
}
const authService = new OCPPAuthServiceImpl(mockStation16)
const identifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_16,
type: IdentifierType.ID_TAG,
value: 'OCPP16_TAG',
}
const authService = new OCPPAuthServiceImpl(mockStation20)
const identifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_20,
type: IdentifierType.E_MAID,
value: 'EMAID123456',
}
const authService = new OCPPAuthServiceImpl(mockStation)
const identifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_16,
type: IdentifierType.ID_TAG,
value: '',
}
const authService = new OCPPAuthServiceImpl(mockStation16)
const identifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_16,
type: IdentifierType.ID_TAG,
value: 'START_TAG',
}
const authService = new OCPPAuthServiceImpl(mockStation16)
const identifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_16,
type: IdentifierType.ID_TAG,
value: 'STOP_TAG',
}
const authService = new OCPPAuthServiceImpl(mockStation20)
const identifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_20,
type: IdentifierType.CENTRAL,
value: 'REMOTE_ID',
}
)
}),
convertToUnifiedIdentifier: identifier => ({
- ocppVersion: OCPPVersion.VERSION_20,
type: IdentifierType.CERTIFICATE,
value: typeof identifier === 'string' ? identifier : JSON.stringify(identifier),
}),
issuerNameHash: 'DEF456',
serialNumber: 'TEST_CERT_001',
},
- ocppVersion: OCPPVersion.VERSION_20,
type: IdentifierType.CERTIFICATE,
value: 'CERT_IDENTIFIER',
},
const config = createTestAuthConfig({ certificateAuthEnabled: true })
const request = createMockAuthRequest({
identifier: {
- ocppVersion: OCPPVersion.VERSION_20,
type: IdentifierType.ID_TAG,
value: 'ID_TAG',
},
})
await it('should return false for OCPP 1.6', () => {
+ const ocpp16Adapter = createMockOCPPAdapter(OCPPVersion.VERSION_16)
+ const ocpp16Strategy = new CertificateAuthStrategy(mockStation, ocpp16Adapter)
+ ocpp16Strategy.initialize(createTestAuthConfig({ certificateAuthEnabled: true }))
+
const config = createTestAuthConfig({ certificateAuthEnabled: true })
const request = createMockAuthRequest({
identifier: {
- ocppVersion: OCPPVersion.VERSION_16,
+ certificateHashData: {
+ hashAlgorithm: 'SHA256',
+ issuerKeyHash: 'ABC123',
+ issuerNameHash: 'DEF456',
+ serialNumber: 'TEST_CERT_001',
+ },
type: IdentifierType.CERTIFICATE,
value: 'CERT',
},
})
- assert.strictEqual(strategy.canHandle(request, config), false)
+ assert.strictEqual(ocpp16Strategy.canHandle(request, config), false)
})
await it('should return false when certificate auth is disabled', () => {
issuerNameHash: 'DEF456',
serialNumber: 'TEST_CERT_001',
},
- ocppVersion: OCPPVersion.VERSION_20,
type: IdentifierType.CERTIFICATE,
value: 'CERT',
},
const config = createTestAuthConfig({ certificateAuthEnabled: true })
const request = createMockAuthRequest({
identifier: {
- ocppVersion: OCPPVersion.VERSION_20,
type: IdentifierType.CERTIFICATE,
value: 'CERT_NO_DATA',
},
issuerNameHash: '789012ghi345',
serialNumber: 'TEST_CERT_001',
},
- ocppVersion: OCPPVersion.VERSION_20,
type: IdentifierType.CERTIFICATE,
value: 'CERT_TEST',
},
issuerNameHash: 'def456',
serialNumber: 'INVALID_CERT',
},
- ocppVersion: OCPPVersion.VERSION_20,
type: IdentifierType.CERTIFICATE,
value: 'CERT_INVALID',
},
issuerNameHash: 'def456',
serialNumber: 'REVOKED_CERT',
},
- ocppVersion: OCPPVersion.VERSION_20,
type: IdentifierType.CERTIFICATE,
value: 'CERT_REVOKED',
},
const config = createTestAuthConfig({ certificateAuthEnabled: true })
const request = createMockAuthRequest({
identifier: {
- ocppVersion: OCPPVersion.VERSION_20,
type: IdentifierType.CERTIFICATE,
value: 'CERT_NO_DATA',
},
issuerNameHash: 'def456',
serialNumber: 'TEST_CERT',
},
- ocppVersion: OCPPVersion.VERSION_20,
type: IdentifierType.CERTIFICATE,
value: 'CERT_BAD_ALGO',
},
issuerNameHash: 'also-not-hex!',
serialNumber: 'TEST_CERT',
},
- ocppVersion: OCPPVersion.VERSION_20,
type: IdentifierType.CERTIFICATE,
value: 'CERT_BAD_HASH',
},
issuerNameHash: 'def456',
serialNumber: 'TEST_CERT_001',
},
- ocppVersion: OCPPVersion.VERSION_20,
type: IdentifierType.CERTIFICATE,
value: 'CERT_TEST',
},
AuthorizationStatus,
IdentifierType,
} from '../../../../../src/charging-station/ocpp/auth/types/AuthTypes.js'
-import { OCPPVersion } from '../../../../../src/types/index.js'
import { standardCleanup } from '../../../../helpers/TestLifecycleHelpers.js'
import {
createMockAuthCache,
})
strategy.initialize(config)
const request = createMockAuthRequest({
- identifier: createMockIdentifier(
- OCPPVersion.VERSION_20,
- 'BLOCKED-TAG',
- IdentifierType.ISO14443
- ),
+ identifier: createMockIdentifier('BLOCKED-TAG', IdentifierType.ISO14443),
})
// Act
})
strategy.initialize(config)
const request = createMockAuthRequest({
- identifier: createMockIdentifier(
- OCPPVersion.VERSION_20,
- 'BLOCKED-TAG',
- IdentifierType.ISO14443
- ),
+ identifier: createMockIdentifier('BLOCKED-TAG', IdentifierType.ISO14443),
})
// Act
})
strategy.initialize(config)
const request = createMockAuthRequest({
- identifier: createMockIdentifier(
- OCPPVersion.VERSION_20,
- 'BLOCKED-TAG',
- IdentifierType.ISO14443
- ),
+ identifier: createMockIdentifier('BLOCKED-TAG', IdentifierType.ISO14443),
})
const result = await strategy.authenticate(request, config)
})
strategy.initialize(config)
const request = createMockAuthRequest({
- identifier: createMockIdentifier(
- OCPPVersion.VERSION_20,
- 'BLOCKED-TAG',
- IdentifierType.ISO14443
- ),
+ identifier: createMockIdentifier('BLOCKED-TAG', IdentifierType.ISO14443),
})
// Act
AuthorizationStatus,
IdentifierType,
} from '../../../../../src/charging-station/ocpp/auth/types/AuthTypes.js'
-import { OCPPVersion } from '../../../../../src/types/index.js'
import { standardCleanup } from '../../../../helpers/TestLifecycleHelpers.js'
import {
createMockAuthCache,
await it('should return true when local auth list is enabled', () => {
const config = createTestAuthConfig({ localAuthListEnabled: true })
const request = createMockAuthRequest({
- identifier: createMockIdentifier(OCPPVersion.VERSION_16, 'TEST_TAG', IdentifierType.ID_TAG),
+ identifier: createMockIdentifier('TEST_TAG', IdentifierType.ID_TAG),
})
assert.strictEqual(strategy.canHandle(request, config), true)
})
await it('should return true when cache is enabled', () => {
const config = createTestAuthConfig({ authorizationCacheEnabled: true })
const request = createMockAuthRequest({
- identifier: createMockIdentifier(OCPPVersion.VERSION_16, 'TEST_TAG', IdentifierType.ID_TAG),
+ identifier: createMockIdentifier('TEST_TAG', IdentifierType.ID_TAG),
})
assert.strictEqual(strategy.canHandle(request, config), true)
})
await it('should return false when nothing is enabled', () => {
const config = createTestAuthConfig()
const request = createMockAuthRequest({
- identifier: createMockIdentifier(OCPPVersion.VERSION_16, 'TEST_TAG', IdentifierType.ID_TAG),
+ identifier: createMockIdentifier('TEST_TAG', IdentifierType.ID_TAG),
})
assert.strictEqual(strategy.canHandle(request, config), false)
})
localAuthListEnabled: true,
})
const request = createMockAuthRequest({
- identifier: createMockIdentifier(
- OCPPVersion.VERSION_16,
- 'LOCAL_TAG',
- IdentifierType.ID_TAG
- ),
+ identifier: createMockIdentifier('LOCAL_TAG', IdentifierType.ID_TAG),
})
const result = await strategy.authenticate(request, config)
const config = createTestAuthConfig({ authorizationCacheEnabled: true })
const request = createMockAuthRequest({
- identifier: createMockIdentifier(
- OCPPVersion.VERSION_16,
- 'CACHED_TAG',
- IdentifierType.ID_TAG
- ),
+ identifier: createMockIdentifier('CACHED_TAG', IdentifierType.ID_TAG),
})
const result = await strategy.authenticate(request, config)
const request = createMockAuthRequest({
allowOffline: true,
context: AuthContext.TRANSACTION_STOP,
- identifier: createMockIdentifier(
- OCPPVersion.VERSION_16,
- 'UNKNOWN_TAG',
- IdentifierType.ID_TAG
- ),
+ identifier: createMockIdentifier('UNKNOWN_TAG', IdentifierType.ID_TAG),
})
const result = await strategy.authenticate(request, config)
await it('should return undefined when no local auth available', async () => {
const config = createTestAuthConfig()
const request = createMockAuthRequest({
- identifier: createMockIdentifier(
- OCPPVersion.VERSION_16,
- 'UNKNOWN_TAG',
- IdentifierType.ID_TAG
- ),
+ identifier: createMockIdentifier('UNKNOWN_TAG', IdentifierType.ID_TAG),
})
const result = await strategy.authenticate(request, config)
await it('should return true when remote auth is enabled', () => {
const config = createTestAuthConfig()
const request = createMockAuthRequest({
- identifier: createMockIdentifier(
- OCPPVersion.VERSION_16,
- 'REMOTE_TAG',
- IdentifierType.ID_TAG
- ),
+ identifier: createMockIdentifier('REMOTE_TAG', IdentifierType.ID_TAG),
})
assert.strictEqual(strategy.canHandle(request, config), true)
})
remoteAuthorization: false,
})
const request = createMockAuthRequest({
- identifier: createMockIdentifier(
- OCPPVersion.VERSION_16,
- 'REMOTE_TAG',
- IdentifierType.ID_TAG
- ),
+ identifier: createMockIdentifier('REMOTE_TAG', IdentifierType.ID_TAG),
})
assert.strictEqual(strategy.canHandle(request, config), false)
})
const strategyNoAdapters = new RemoteAuthStrategy()
const config = createTestAuthConfig()
const request = createMockAuthRequest({
- identifier: createMockIdentifier(
- OCPPVersion.VERSION_16,
- 'REMOTE_TAG',
- IdentifierType.ID_TAG
- ),
+ identifier: createMockIdentifier('REMOTE_TAG', IdentifierType.ID_TAG),
})
assert.strictEqual(strategyNoAdapters.canHandle(request, config), false)
})
await it('should authenticate using adapter', async () => {
const config = createTestAuthConfig({ authorizationCacheEnabled: true })
const request = createMockAuthRequest({
- identifier: createMockIdentifier(
- OCPPVersion.VERSION_16,
- 'REMOTE_TAG',
- IdentifierType.ID_TAG
- ),
+ identifier: createMockIdentifier('REMOTE_TAG', IdentifierType.ID_TAG),
})
const result = await strategy.authenticate(request, config)
authorizationCacheLifetime: 300,
})
const request = createMockAuthRequest({
- identifier: createMockIdentifier(
- OCPPVersion.VERSION_16,
- 'CACHE_TAG',
- IdentifierType.ID_TAG
- ),
+ identifier: createMockIdentifier('CACHE_TAG', IdentifierType.ID_TAG),
})
await strategy.authenticate(request, config)
authorizationCacheLifetime: 300,
})
const request = createMockAuthRequest({
- identifier: createMockIdentifier(
- OCPPVersion.VERSION_16,
- 'BLOCKED_TAG',
- IdentifierType.ID_TAG
- ),
+ identifier: createMockIdentifier('BLOCKED_TAG', IdentifierType.ID_TAG),
})
await strategy.authenticate(request, config)
authorizationCacheLifetime: 300,
})
const request = createMockAuthRequest({
- identifier: createMockIdentifier(
- OCPPVersion.VERSION_16,
- 'EXPIRED_TAG',
- IdentifierType.ID_TAG
- ),
+ identifier: createMockIdentifier('EXPIRED_TAG', IdentifierType.ID_TAG),
})
await strategy.authenticate(request, config)
authorizationCacheLifetime: 300,
})
const request = createMockAuthRequest({
- identifier: createMockIdentifier(
- OCPPVersion.VERSION_16,
- 'INVALID_TAG',
- IdentifierType.ID_TAG
- ),
+ identifier: createMockIdentifier('INVALID_TAG', IdentifierType.ID_TAG),
})
await strategy.authenticate(request, config)
authorizationCacheLifetime: 300,
})
const request = createMockAuthRequest({
- identifier: createMockIdentifier(
- OCPPVersion.VERSION_16,
- 'ACCEPTED_TAG',
- IdentifierType.ID_TAG
- ),
+ identifier: createMockIdentifier('ACCEPTED_TAG', IdentifierType.ID_TAG),
})
await strategy.authenticate(request, config)
const config = createTestAuthConfig()
const request = createMockAuthRequest({
- identifier: createMockIdentifier(
- OCPPVersion.VERSION_16,
- 'UNAVAILABLE_TAG',
- IdentifierType.ID_TAG
- ),
+ identifier: createMockIdentifier('UNAVAILABLE_TAG', IdentifierType.ID_TAG),
})
const result = await strategy.authenticate(request, config)
const config = createTestAuthConfig()
const request = createMockAuthRequest({
identifier: {
- ocppVersion: OCPPVersion.VERSION_201,
type: IdentifierType.ID_TAG,
value: 'UNKNOWN_VERSION_TAG',
},
const config = createTestAuthConfig()
const request = createMockAuthRequest({
- identifier: createMockIdentifier(
- OCPPVersion.VERSION_16,
- 'ERROR_TAG',
- IdentifierType.ID_TAG
- ),
+ identifier: createMockIdentifier('ERROR_TAG', IdentifierType.ID_TAG),
})
const result = await strategy.authenticate(request, config)
localAuthListEnabled: true,
})
const request = createMockAuthRequest({
- identifier: createMockIdentifier(
- OCPPVersion.VERSION_16,
- 'LOCAL_AUTH_TAG',
- IdentifierType.ID_TAG
- ),
+ identifier: createMockIdentifier('LOCAL_AUTH_TAG', IdentifierType.ID_TAG),
})
await strategy.authenticate(request, config)
localAuthListEnabled: true,
})
const request = createMockAuthRequest({
- identifier: createMockIdentifier(
- OCPPVersion.VERSION_16,
- 'REMOTE_AUTH_TAG',
- IdentifierType.ID_TAG
- ),
+ identifier: createMockIdentifier('REMOTE_AUTH_TAG', IdentifierType.ID_TAG),
})
await strategy.authenticate(request, config)
const config = createTestAuthConfig()
const request = createMockAuthRequest({
- identifier: createMockIdentifier(OCPPVersion.VERSION_16, 'TEST', IdentifierType.ID_TAG),
+ identifier: createMockIdentifier('TEST', IdentifierType.ID_TAG),
})
assert.strictEqual(newStrategy.canHandle(request, config), true)
const config = createTestAuthConfig()
const request = createMockAuthRequest({
- identifier: createMockIdentifier(OCPPVersion.VERSION_16, 'TEST', IdentifierType.ID_TAG),
+ identifier: createMockIdentifier('TEST', IdentifierType.ID_TAG),
})
assert.strictEqual(strategy.canHandle(request, config), false)
await describe('UnifiedIdentifier', async () => {
await it('should create valid OCPP 1.6 identifier', () => {
const identifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_16,
type: IdentifierType.ID_TAG,
value: 'VALID_ID_TAG',
}
assert.strictEqual(identifier.value, 'VALID_ID_TAG')
assert.strictEqual(identifier.type, IdentifierType.ID_TAG)
- assert.strictEqual(identifier.ocppVersion, OCPPVersion.VERSION_16)
})
await it('should create valid OCPP 2.0 identifier with additional info', () => {
contractId: 'CONTRACT123',
issuer: 'EMSProvider',
},
- ocppVersion: OCPPVersion.VERSION_20,
type: IdentifierType.E_MAID,
value: 'EMAID123456',
}
assert.strictEqual(identifier.value, 'EMAID123456')
assert.strictEqual(identifier.type, IdentifierType.E_MAID)
- assert.strictEqual(identifier.ocppVersion, OCPPVersion.VERSION_20)
assert.notStrictEqual(identifier.additionalInfo, undefined)
assert.strictEqual(identifier.additionalInfo?.issuer, 'EMSProvider')
})
issuerNameHash: 'ISSUER_HASH',
serialNumber: '123456',
},
- ocppVersion: OCPPVersion.VERSION_20,
type: IdentifierType.CERTIFICATE,
value: 'CERT_IDENTIFIER',
}
type UnifiedIdentifier,
} from '../../../../../src/charging-station/ocpp/auth/types/AuthTypes.js'
import { AuthHelpers } from '../../../../../src/charging-station/ocpp/auth/utils/AuthHelpers.js'
-import { OCPPVersion } from '../../../../../src/types/index.js'
import { standardCleanup } from '../../../../helpers/TestLifecycleHelpers.js'
await describe('AuthHelpers', async () => {
await describe('createAuthRequest', async () => {
await it('should create basic auth request with minimal parameters', () => {
const identifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_16,
type: IdentifierType.ID_TAG,
value: 'TEST123',
}
await it('should create auth request with connector ID', () => {
const identifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_20,
type: IdentifierType.LOCAL,
value: 'LOCAL001',
}
await it('should create auth request with metadata', () => {
const identifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_20,
type: IdentifierType.CENTRAL,
value: 'CENTRAL001',
}
await it('should format error message with truncated identifier', () => {
const error = new Error('Connection timeout')
const identifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_16,
type: IdentifierType.ID_TAG,
value: 'VERY_LONG_IDENTIFIER_VALUE_12345',
}
await it('should handle short identifiers correctly', () => {
const error = new Error('Invalid format')
const identifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_20,
type: IdentifierType.LOCAL,
value: 'SHORT',
}
type UnifiedIdentifier,
} from '../../../../../src/charging-station/ocpp/auth/types/AuthTypes.js'
import { AuthValidators } from '../../../../../src/charging-station/ocpp/auth/utils/AuthValidators.js'
-import { OCPPVersion } from '../../../../../src/types/index.js'
import { standardCleanup } from '../../../../helpers/TestLifecycleHelpers.js'
await describe('AuthValidators', async () => {
await it('should return false for empty value', () => {
const identifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_16,
type: IdentifierType.ID_TAG,
value: '',
}
await it('should return false for ID_TAG exceeding 20 characters', () => {
const identifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_16,
type: IdentifierType.ID_TAG,
value: 'VERY_LONG_IDENTIFIER_VALUE_123456789',
}
await it('should return true for valid ID_TAG within 20 characters', () => {
const identifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_16,
type: IdentifierType.ID_TAG,
value: 'VALID_ID_TAG',
}
await it('should return true for OCPP 2.0 LOCAL type within 36 characters', () => {
const identifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_20,
type: IdentifierType.LOCAL,
value: 'LOCAL_TOKEN_123',
}
await it('should return false for OCPP 2.0 type exceeding 36 characters', () => {
const identifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_20,
type: IdentifierType.CENTRAL,
value: 'VERY_LONG_CENTRAL_IDENTIFIER_VALUE_1234567890123456789',
}
await it('should return true for CENTRAL type within 36 characters', () => {
const identifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_20,
type: IdentifierType.CENTRAL,
value: 'CENTRAL_TOKEN',
}
await it('should return true for E_MAID type', () => {
const identifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_20,
type: IdentifierType.E_MAID,
value: 'DE-ABC-123456',
}
await it('should return true for ISO14443 type', () => {
const identifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_20,
type: IdentifierType.ISO14443,
value: '04A2B3C4D5E6F7',
}
await it('should return true for KEY_CODE type', () => {
const identifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_20,
type: IdentifierType.KEY_CODE,
value: '1234',
}
await it('should return true for MAC_ADDRESS type', () => {
const identifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_20,
type: IdentifierType.MAC_ADDRESS,
value: '00:11:22:33:44:55',
}
await it('should return true for NO_AUTHORIZATION type', () => {
const identifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_20,
type: IdentifierType.NO_AUTHORIZATION,
value: 'NO_AUTH',
}
await it('should return false for unsupported type', () => {
const identifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_20,
// @ts-expect-error: Testing invalid type
type: 'UNSUPPORTED_TYPE',
value: 'VALUE',
AuthorizationStatus,
IdentifierType,
} from '../../src/charging-station/ocpp/auth/types/AuthTypes.js'
-import { OCPPVersion } from '../../src/types/index.js'
import { logger } from '../../src/utils/index.js'
export class OCPPAuthIntegrationTest {
private async testCacheOperations (): Promise<void> {
const testIdentifier: UnifiedIdentifier = {
- ocppVersion:
- this.chargingStation.stationInfo?.ocppVersion === OCPPVersion.VERSION_16
- ? OCPPVersion.VERSION_16
- : OCPPVersion.VERSION_201,
type: IdentifierType.LOCAL,
value: 'CACHE_TEST_ID',
}
private async testErrorHandling (): Promise<void> {
const invalidIdentifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_16,
type: IdentifierType.ISO14443,
value: '',
}
private async testOCPP16AuthFlow (): Promise<void> {
const identifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_16,
type: IdentifierType.ISO14443,
value: 'VALID_ID_123',
}
private async testOCPP20AuthFlow (): Promise<void> {
const identifier: UnifiedIdentifier = {
- ocppVersion: OCPPVersion.VERSION_20,
type: IdentifierType.ISO15693,
value: 'VALID_ID_456',
}
}
const identifier: UnifiedIdentifier = {
- ocppVersion:
- this.chargingStation.stationInfo?.ocppVersion === OCPPVersion.VERSION_16
- ? OCPPVersion.VERSION_16
- : OCPPVersion.VERSION_20,
type: IdentifierType.ISO14443,
value: 'PERF_TEST_ID',
}
}
const testIdentifier: UnifiedIdentifier = {
- ocppVersion:
- this.chargingStation.stationInfo?.ocppVersion === OCPPVersion.VERSION_16
- ? OCPPVersion.VERSION_16
- : OCPPVersion.VERSION_20,
type: IdentifierType.ISO14443,
value: 'TEST123',
}