diff --git a/ballerina/Ballerina.toml b/ballerina/Ballerina.toml index 135ddb01..14a7d8f6 100644 --- a/ballerina/Ballerina.toml +++ b/ballerina/Ballerina.toml @@ -1,7 +1,7 @@ [package] org = "ballerina" name = "oauth2" -version = "2.12.0" +version = "2.12.1" authors = ["Ballerina"] keywords = ["security", "authorization", "introspection"] repository = "https://github.com/ballerina-platform/module-ballerina-oauth2" @@ -15,5 +15,5 @@ graalvmCompatible = true [[platform.java17.dependency]] groupId = "io.ballerina.stdlib" artifactId = "oauth2-native" -version = "2.12.0" -path = "../native/build/libs/oauth2-native-2.12.0.jar" +version = "2.12.1" +path = "../native/build/libs/oauth2-native-2.12.1-SNAPSHOT.jar" diff --git a/ballerina/Dependencies.toml b/ballerina/Dependencies.toml index e043308b..a600c25a 100644 --- a/ballerina/Dependencies.toml +++ b/ballerina/Dependencies.toml @@ -130,7 +130,7 @@ modules = [ [[package]] org = "ballerina" name = "oauth2" -version = "2.12.0" +version = "2.12.1" dependencies = [ {org = "ballerina", name = "cache"}, {org = "ballerina", name = "crypto"}, diff --git a/ballerina/listener_oauth2_provider.bal b/ballerina/listener_oauth2_provider.bal index 7b5daffd..435268f2 100644 --- a/ballerina/listener_oauth2_provider.bal +++ b/ballerina/listener_oauth2_provider.bal @@ -210,7 +210,7 @@ isolated function prepareIntrospectionResponse(json payload) returns Introspecti introspectionResponse.tokenType = payloadMap[key]; } EXP => { - introspectionResponse.exp = payloadMap[key]; + introspectionResponse.exp = parseExpClaim(payloadMap[key]); } IAT => { introspectionResponse.iat = payloadMap[key]; @@ -239,7 +239,7 @@ isolated function prepareIntrospectionResponse(json payload) returns Introspecti } isolated function addToCache(cache:Cache oauth2Cache, string token, IntrospectionResponse response, - decimal defaultTokenExpTime) { + decimal defaultTokenExpTime) { cache:Error? result; if response?.exp is int { result = oauth2Cache.put(token, response); @@ -260,7 +260,7 @@ isolated function validateFromCache(cache:Cache oauth2Cache, string token) retur return; } if cachedEntry is any { - IntrospectionResponse response = cachedEntry; + IntrospectionResponse response = cachedEntry; int? expTime = response?.exp; // The `expTime` can be `()`. This means that the `defaultTokenExpTime` is not exceeded yet. // Hence, the token is still valid. If the `expTime` is provided in int, convert this to the current time and @@ -278,3 +278,10 @@ isolated function validateFromCache(cache:Cache oauth2Cache, string token) retur } return; } + +isolated function parseExpClaim(json expClaim) returns int|() { + if expClaim is string { + return checkpanic int:fromString(expClaim); + } + return expClaim; +} diff --git a/ballerina/tests/listener_oauth2_provider_test.bal b/ballerina/tests/listener_oauth2_provider_test.bal index 3540a1d6..9d56093f 100644 --- a/ballerina/tests/listener_oauth2_provider_test.bal +++ b/ballerina/tests/listener_oauth2_provider_test.bal @@ -545,3 +545,17 @@ isolated function testTokenIntrospectionRequestWithSecureSocketAndWithHttpUrlSch test:assertEquals(response?.jti, "JlbmMiOiJBMTI4Q0JDLUhTMjU2In"); test:assertEquals(response?.jti, "JlbmMiOiJBMTI4Q0JDLUhTMjU2In"); } + +// Test that the `exp` field is correctly parsed as an integer when given an example string value for `exp` field +@test:Config {} +isolated function testPrepareIntrospectionResponseWithStringExpClaim() { + json simulatedResponse = { + active: true, + exp: "1672531199", + scope: "read write", + client_id: "test_client_id", + username: "test_user" + }; + IntrospectionResponse response = prepareIntrospectionResponse(simulatedResponse); + test:assertEquals(response.exp, 1672531199); +}