7
7
*/
8
8
component accessors = " true" singleton {
9
9
10
- // DI
11
- property name = " jwt" inject = " provider:JWTService@jwt" ;
10
+ /* ********************************************************************************************/
11
+ /* * DI **/
12
+ /* ********************************************************************************************/
13
+
14
+ property name = " jwt" inject = " provider:jwt@jwtcfml" ;
12
15
property name = " wirebox" inject = " wirebox" ;
13
16
property name = " settings" inject = " coldbox:moduleSettings:cbSecurity" ;
14
17
property name = " interceptorService" inject = " coldbox:interceptorService" ;
15
18
property name = " requestService" inject = " coldbox:requestService" ;
16
19
property name = " log" inject = " logbox:logger:{this}" ;
17
20
21
+ /* ********************************************************************************************/
22
+ /* * PROPERTIES **/
23
+ /* ********************************************************************************************/
24
+
18
25
/**
19
26
* The auth service in use
20
27
*/
@@ -30,6 +37,10 @@ component accessors="true" singleton {
30
37
*/
31
38
property name = " tokenStorage" ;
32
39
40
+ /* ********************************************************************************************/
41
+ /* * STATIC PROPERTIES **/
42
+ /* ********************************************************************************************/
43
+
33
44
// Required Claims
34
45
variables .REQUIRED_CLAIMS = [
35
46
" jti" ,
@@ -40,6 +51,41 @@ component accessors="true" singleton {
40
51
" scopes"
41
52
];
42
53
54
+ // Default Settings
55
+ variables .DEFAULT_SETTINGS = {
56
+ // The jwt secret encoding key
57
+ " secretKey" : " " ,
58
+ // The Custom header to inspect for tokens
59
+ " customAuthHeader" : " x-auth-token" ,
60
+ // The expiration in minutes for the jwt tokens
61
+ " expiration" : 60 ,
62
+ // If true, enables refresh tokens, longer lived tokens (not implemented yet)
63
+ " enableRefreshTokens" : false ,
64
+ // The default expiration for refresh tokens, defaults to 30 days
65
+ " refreshExpiration" : 43200 ,
66
+ // encryption algorithm to use, valid algorithms are: HS256, HS384, and HS512
67
+ " algorithm" : " HS512" ,
68
+ // Which claims neds to be present on the jwt token or `TokenInvalidException` upon verification and decoding
69
+ " requiredClaims" : [] ,
70
+ // The token storage settings
71
+ " tokenStorage" : {
72
+ // enable or not, default is true
73
+ " enabled" : true ,
74
+ // A cache key prefix to use when storing the tokens
75
+ " keyPrefix" : " cbjwt_" ,
76
+ // The driver to use: db, cachebox or a WireBox ID
77
+ " driver" : " cachebox" ,
78
+ // Driver specific properties
79
+ " properties" : {
80
+ " cacheName" : " default"
81
+ }
82
+ }
83
+ };
84
+
85
+ /* ********************************************************************************************/
86
+ /* * CONSTRUCTOR & STARTUP **/
87
+ /* ********************************************************************************************/
88
+
43
89
/**
44
90
* Constructor
45
91
*/
@@ -48,17 +94,24 @@ component accessors="true" singleton {
48
94
}
49
95
50
96
/**
51
- * Runs after DI
97
+ * Runs after DI, here is where we setup the jwt settings for operation
52
98
*/
53
99
function onDIComplete (){
54
- // Verify a few settings just in case
100
+ // If no settings defined, use the defaults
101
+ if ( ! structKeyExists ( variables .settings , " jwt" ) ){
102
+ variables .settings .jwt = variables .DEFAULT_SETTINGS ;
103
+ }
104
+
105
+ // Incorporate defaults into incoming data
106
+ structAppend ( variables .settings .jwt , variables .DEFAULT_SETTINGS , false );
107
+ structAppend ( variables .settings .jwt .tokenStorage , variables .DEFAULT_SETTINGS .tokenStorage , false );
108
+
109
+ // If no secret is defined, then let's create one dynamically
55
110
if ( isNull ( variables .settings .jwt .secretKey ) || ! len ( variables .settings .jwt .secretKey ) ) {
56
- throw (
57
- message = " The JWT secret key cannot be empty, please fill this out in your `config/ColdBox.cfc` under your cbsecurity settings" ,
58
- detail = " cbsecurity.jwt.secretKey" ,
59
- type = " InvalidSecretKey"
60
- )
111
+ variables .settings .jwt .secretKey = generateSecretKey ( " blowfish" , 448 );
112
+ variables .log .warn ( " No jwt secret key setting found, automatically generating one" );
61
113
}
114
+
62
115
}
63
116
64
117
/* ***********************************************************************************/
@@ -326,8 +379,14 @@ component accessors="true" singleton {
326
379
}
327
380
} );
328
381
382
+
329
383
// Verify Expiration first
330
- if ( dateCompare ( fromEpoch ( decodedToken .exp ), now () ) < 0 ) {
384
+ if (
385
+ dateCompare (
386
+ ( isDate ( decodedToken .exp ) ? decodedToken .exp : fromEpoch ( decodedToken .exp ) ),
387
+ now ()
388
+ ) < 0
389
+ ) {
331
390
if ( variables .log .canWarn () ) {
332
391
variables .log .warn ( " Token rejected, it has expired" , decodedToken );
333
392
}
@@ -477,11 +536,17 @@ component accessors="true" singleton {
477
536
* @token The token to validate
478
537
*/
479
538
boolean function verify ( required token ){
480
- return variables .jwt .verify (
481
- arguments .token ,
482
- variables .settings .jwt .secretKey ,
483
- variables .settings .jwt .algorithm
484
- );
539
+ try {
540
+ variables .jwt .decode (
541
+ token = arguments .token ,
542
+ key = variables .settings .jwt .secretKey ,
543
+ algorithms = variables .settings .jwt .algorithm ,
544
+ verify = false
545
+ );
546
+ return true ;
547
+ } catch ( Any e ){
548
+ return false ;
549
+ }
485
550
}
486
551
487
552
/**
@@ -494,9 +559,9 @@ component accessors="true" singleton {
494
559
struct function decode ( required token ){
495
560
try {
496
561
return variables .jwt .decode (
497
- arguments .token ,
498
- variables .settings .jwt .secretKey ,
499
- variables .settings .jwt .algorithm
562
+ token = arguments .token ,
563
+ key = variables .settings .jwt .secretKey ,
564
+ algorithms = variables .settings .jwt .algorithm
500
565
);
501
566
} catch ( any e ) {
502
567
throw (
@@ -567,7 +632,9 @@ component accessors="true" singleton {
567
632
}
568
633
569
634
/**
570
- * Get the appropriate token storage
635
+ * Get the appropriate token storage provider
636
+ *
637
+ * @return cbsecurity.interfaces.jwt.IJwtStorage
571
638
*/
572
639
function getTokenStorage (){
573
640
// If loaded, use it!
@@ -725,4 +792,4 @@ component accessors="true" singleton {
725
792
.len ();
726
793
}
727
794
728
- }
795
+ }
0 commit comments