3030import com .google .firebase .internal .FirebaseProcessEnvironment ;
3131import com .google .firebase .testing .ServiceAccount ;
3232import com .google .firebase .testing .TestUtils ;
33+ import com .nimbusds .jose .JOSEException ;
3334import com .nimbusds .jose .JOSEObjectType ;
3435import com .nimbusds .jose .JWSAlgorithm ;
3536import com .nimbusds .jose .JWSHeader ;
3940import com .nimbusds .jose .jwk .Curve ;
4041import com .nimbusds .jose .jwk .ECKey ;
4142import com .nimbusds .jose .jwk .gen .ECKeyGenerator ;
43+ import com .nimbusds .jose .proc .BadJOSEException ;
4244import com .nimbusds .jose .proc .SecurityContext ;
4345import com .nimbusds .jwt .JWTClaimsSet ;
4446import com .nimbusds .jwt .SignedJWT ;
5658import org .mockito .MockitoAnnotations ;
5759
5860public class FpnvTokenVerifierTest {
61+ private static final String PROJECT_ID = "mock-project-id" ;
5962 private static final FirebaseOptions firebaseOptions = FirebaseOptions .builder ()
63+ .setProjectId (PROJECT_ID )
6064 .setCredentials (TestUtils .getCertCredential (ServiceAccount .OWNER .asStream ()))
6165 .build ();
62- private static final String PROJECT_ID = "mock-project-id" ;
6366 private static final String ISSUER = "https://fpnv.googleapis.com/projects/" + PROJECT_ID ;
6467 private static final String [] AUD = new String []{
6568 ISSUER ,
@@ -73,6 +76,7 @@ public class FpnvTokenVerifierTest {
7376 private KeyPair rsaKeyPair ;
7477 private ECKey ecKey ;
7578 private JWSHeader header ;
79+ private JWTClaimsSet claims ;
7680
7781 @ Before
7882 public void setUp () throws Exception {
@@ -99,6 +103,15 @@ public void setUp() throws Exception {
99103 .keyID (ecKey .getKeyID ())
100104 .type (JOSEObjectType .JWT )
101105 .build ();
106+
107+ // Create a valid JWTClaimsSet
108+ claims = new JWTClaimsSet .Builder ()
109+ .issuer (ISSUER )
110+ .audience (Arrays .asList (AUD ))
111+ .subject ("+15551234567" )
112+ .issueTime (new Date ())
113+ .expirationTime (new Date (System .currentTimeMillis () + 10000 ))
114+ .build ();
102115 }
103116
104117 @ After
@@ -124,18 +137,15 @@ private String createToken(JWSHeader header, JWTClaimsSet claims) throws Excepti
124137 }
125138
126139 @ Test
127- public void testVerifyToken_Success () throws Exception {
128- Date now = new Date ();
129- Date exp = new Date (now .getTime () + 3600 * 1000 ); // 1 hour valid
130-
131- JWTClaimsSet claims = new JWTClaimsSet .Builder ()
132- .issuer (ISSUER )
133- .audience (Arrays .asList (AUD ))
134- .subject ("+15551234567" )
135- .issueTime (now )
136- .expirationTime (exp )
137- .build ();
140+ public void testVerifyToken_NullOrEmptyToken () {
141+ IllegalArgumentException e = assertThrows (IllegalArgumentException .class , () ->
142+ verifier .verifyToken ("" )
143+ );
144+ assertTrue (e .getMessage ().contains ("FPNV token must not be null" ));
145+ }
138146
147+ @ Test
148+ public void testVerifyToken_Success () throws Exception {
139149 String tokenString = createToken (header , claims );
140150
141151 // 1. Mock the processor to return these claims (skipping real signature verification)
@@ -167,6 +177,25 @@ public void testVerifyToken_Header_WrongAlgorithm() throws Exception {
167177 assertTrue (e .getMessage ().contains ("algorithm" ));
168178 }
169179
180+ @ Test
181+ public void testVerifyToken_Header_WrongTyp () throws Exception {
182+ JWSHeader header = new JWSHeader
183+ .Builder (JWSAlgorithm .ES256 )
184+ .keyID (ecKey .getKeyID ())
185+ .type (JOSEObjectType .JOSE )
186+ .build ();
187+ JWTClaimsSet claims = new JWTClaimsSet .Builder ().build ();
188+
189+ String tokenString = createToken (header , claims );
190+
191+ FirebasePnvException e = assertThrows (FirebasePnvException .class , () ->
192+ verifier .verifyToken (tokenString )
193+ );
194+
195+ assertEquals (FirebasePnvErrorCode .INVALID_ARGUMENT , e .getFpnvErrorCode ());
196+ assertTrue (e .getMessage ().contains ("has incorrect 'typ'" ));
197+ }
198+
170199 @ Test
171200 public void testVerifyToken_Header_MissingKeyId () throws Exception {
172201 // ES256 but missing 'kid'
@@ -195,7 +224,6 @@ public void testVerifyToken_Claims_Expired() throws Exception {
195224 String tokenString = createToken (header , claims );
196225 ExpiredJWTException error = new ExpiredJWTException ("Bad token" );
197226
198- // Mock processor returning the expired claims
199227 when (mockJwtProcessor .process (any (SignedJWT .class ), any ())).thenThrow (error );
200228
201229 FirebasePnvException e = assertThrows (FirebasePnvException .class , () ->
@@ -243,4 +271,57 @@ public void testVerifyToken_Claims_NoSubject() throws Exception {
243271 assertEquals (FirebasePnvErrorCode .INVALID_TOKEN , e .getFpnvErrorCode ());
244272 assertTrue (e .getMessage ().contains ("Token has an empty 'sub' (phone number)" ));
245273 }
274+
275+ @ Test
276+ public void testVerifyToken_ParseException () {
277+ FirebasePnvException e = assertThrows (FirebasePnvException .class , () ->
278+ verifier .verifyToken (" " )
279+ );
280+ assertEquals (FirebasePnvErrorCode .INVALID_TOKEN , e .getFpnvErrorCode ());
281+ assertTrue (e .getMessage ().contains ("Failed to parse JWT token" ));
282+ }
283+
284+ @ Test
285+ public void testVerifyToken_BadJOSEException () throws Exception {
286+ String tokenString = createToken (header , claims );
287+ String errorMessage = "BadJOSEException" ;
288+ BadJOSEException error = new BadJOSEException (errorMessage );
289+
290+ when (mockJwtProcessor .process (any (SignedJWT .class ), any ())).thenThrow (error );
291+
292+ FirebasePnvException e = assertThrows (FirebasePnvException .class , () ->
293+ verifier .verifyToken (tokenString )
294+ );
295+
296+ assertEquals (FirebasePnvErrorCode .INVALID_TOKEN , e .getFpnvErrorCode ());
297+ assertEquals (
298+ "Check your project: "
299+ + PROJECT_ID
300+ + ". FPNV token is invalid: "
301+ + errorMessage ,
302+ e .getMessage ()
303+ );
304+ }
305+
306+ @ Test
307+ public void testVerifyToken_JOSEException () throws Exception {
308+ String tokenString = createToken (header , claims );
309+ String errorMessage = "JOSEException" ;
310+ JOSEException error = new JOSEException (errorMessage );
311+
312+ when (mockJwtProcessor .process (any (SignedJWT .class ), any ())).thenThrow (error );
313+
314+ FirebasePnvException e = assertThrows (FirebasePnvException .class , () ->
315+ verifier .verifyToken (tokenString )
316+ );
317+
318+ assertEquals (FirebasePnvErrorCode .INTERNAL_ERROR , e .getFpnvErrorCode ());
319+ assertEquals (
320+ "Check your project: "
321+ + PROJECT_ID
322+ + ". Failed to verify FPNV token signature: "
323+ + errorMessage ,
324+ e .getMessage ()
325+ );
326+ }
246327}
0 commit comments