Skip to content

Commit

Permalink
Securized class
Browse files Browse the repository at this point in the history
  • Loading branch information
matteobaccan committed Mar 11, 2022
1 parent 418a74a commit 8d60557
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 42 deletions.
Binary file modified lib/jwt.hrb
Binary file not shown.
Binary file modified out/jwttest.hrb
Binary file not shown.
16 changes: 9 additions & 7 deletions out/jwttest.log
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@

OK - signature verified
OK - signature verified
OK - signature verified
OK - signature verified
OK - signature verified
OK - signature verified
Token expired
OK - data verified
OK - data verified
OK - data verified
OK - data verified
OK - data verified
OK - data verified
Token expired
OK - data verified
OK - data verified
85 changes: 52 additions & 33 deletions src/jwt.prg
Original file line number Diff line number Diff line change
Expand Up @@ -16,53 +16,72 @@

CLASS JWT

DATA cSecret
DATA aHeader
DATA aPayload
DATA cError
HIDDEN:

CLASSDATA cSecret
CLASSDATA aHeader
CLASSDATA aPayload
CLASSDATA cError

METHOD Base64UrlEncode( cData )
METHOD Base64UrlDecode( cData )
METHOD ByteToString( cData )
METHOD GetSignature( cHeader, cPayload, cSecret, cAlgorithm )

EXPORTED:

METHOD New() CONSTRUCTOR

// Header
METHOD SetType( cType )
METHOD GetType() INLINE ::aHeader[ 'typ' ]
METHOD SetContentType( cContentType ) INLINE ::aHeader[ 'cty' ] := cContentType
METHOD GetContentType() INLINE ::aHeader[ 'cty' ]
METHOD SetAlgorithm( cAlgorithm )
METHOD GetAlgorithm() INLINE ::aHeader[ 'alg' ]

// Payload
METHOD SetIssuer( cIssuer ) INLINE ::aPayload[ 'iss' ] := cIssuer
METHOD GetIssuer() INLINE ::aPayload[ 'iss' ]
METHOD SetSubject( cSubject ) INLINE ::aPayload[ 'sub' ] := cSubject
METHOD GetSubject() INLINE ::aPayload[ 'sub' ]
METHOD SetAudience( cAudience ) INLINE ::aPayload[ 'aud' ] := cAudience
METHOD GetAudience() INLINE ::aPayload[ 'aud' ]
METHOD SetExpration( nExpiration ) INLINE ::aPayload[ 'exp' ] := nExpiration
METHOD GetExpration() INLINE ::aPayload[ 'exp' ]
METHOD SetNotBefore( nNotBefore ) INLINE ::aPayload[ 'nbf' ] := nNotBefore
METHOD GetNotBefore() INLINE ::aPayload[ 'nbf' ]
METHOD SetIssuedAt( nIssuedAt ) INLINE ::aPayload[ 'iat' ] := nIssuedAt
METHOD GetIssuedAt() INLINE ::aPayload[ 'iat' ]
METHOD SetJWTId( cJWTId ) INLINE ::aPayload[ 'jti' ] := cJWTId
METHOD GetJWTId() INLINE ::aPayload[ 'jti' ]

// Payload methods
METHOD SetPayloadData( cKey, uValue ) INLINE ::aPayload[ cKey ] := uValue
METHOD GetPayloadData( cKey ) INLINE ::aPayload[ cKey ]

// Secret
METHOD SetSecret( cSecret ) INLINE ::cSecret := cSecret
METHOD GetSecret() INLINE ::cSecret

// Error
METHOD GetError() INLINE ::cError

// Cleanup data
// Cleanup: aHeader, aPayload, cError, cSecret
METHOD Reset()

// Encode a JWT
// Encode a JWT and return it
METHOD Encode()

// Decode a JWT
METHOD Decode( cJWT, cSecret )

// Payload methods
METHOD SetPayloadData( cKey, uValue ) INLINE ::aPayload[ cKey ] := uValue
METHOD GetPayloadData( cKey ) INLINE ::aPayload[ cKey ]

// Getter internal data
METHOD GetPayload() INLINE ::aPayload
METHOD GetHeader() INLINE ::aHeader
METHOD GetError() INLINE ::cError
// Getter internal data with internal exposion
METHOD GetPayload() INLINE hb_hClone(::aPayload)
METHOD GetHeader() INLINE hb_hClone(::aHeader)

METHOD Base64UrlEncode( cData )
METHOD Base64UrlDecode( cData )
METHOD ByteToString( cData )
METHOD GetSignature( cHeader, cPayload, cSecret, cAlgorithm )
METHOD getposix()
// Helper method for expiration setting
METHOD GetSeconds()

ENDCLASS

Expand All @@ -74,25 +93,25 @@ RETU SELF
METHOD SetType( cType ) CLASS JWT
LOCAL bRet := .F.

if cType=="JWT"
IF cType=="JWT"
::aHeader[ 'typ' ] := cType
else
ELSE
bRet := .F.
::cError := "Invalid type [" +cType +"]"
endif
ENDIF

RETU bRet

// Mandatory
METHOD SetAlgorithm( cAlgorithm ) CLASS JWT
LOCAL bRet := .F.

if cAlgorithm=="HS256" .OR. cAlgorithm=="HS384" .OR. cAlgorithm=="HS512"
IF cAlgorithm=="HS256" .OR. cAlgorithm=="HS384" .OR. cAlgorithm=="HS512"
::aHeader[ 'alg' ] := cAlgorithm
else
ELSE
bRet := .F.
::cError := "Invalid algorithm [" +cAlgorithm +"]"
endif
ENDIF

RETU bRet

Expand Down Expand Up @@ -144,7 +163,7 @@ METHOD ByteToString( cData ) CLASS JWT

RETU cRet

METHOD GetSignature( cHeader, cPayload, cSecret, cAlgorithm ) CLASS JWT
METHOD GetSignature( cHeader, cPayload, cSecret, cAlgorithm ) CLASS JWT
LOCAL cSignature := ""

DO CASE
Expand All @@ -157,7 +176,7 @@ RETU cRet
OTHERWISE
::cError := "INVALID ALGORITHM"
ENDCASE
RETU cSignature
RETU cSignature

METHOD Decode( cJWT, cSecret ) CLASS JWT

Expand Down Expand Up @@ -194,19 +213,19 @@ METHOD Decode( cJWT, cSecret ) CLASS JWT

// Check expiration
IF hb_HHasKey(::aPayLoad,'exp')
IF ::aPayLoad[ 'exp' ] < ::getposix()
IF ::aPayLoad[ 'exp' ] < ::GetSeconds()
::cError := "Token expired"
RETU .F.
ENDIF
ENDIF

RETU .T.

METHOD getposix() CLASS JWT
METHOD GetSeconds() CLASS JWT

LOCAL posixday := date() - STOD("19700101")
LOCAL cTime := time()
LOCAL posixsec := posixday * 24 * 60 * 60
LOCAL posixday := date() - STOD("19700101")
LOCAL cTime := time()
LOCAL posixsec := posixday * 24 * 60 * 60

return posixsec + (int(val(substr(cTime,1,2))) * 3600) + (int(val(substr(cTime,4.2))) * 60) + ( int(val(substr(cTime,7,2))) )
RETU posixsec + (int(val(substr(cTime,1,2))) * 3600) + (int(val(substr(cTime,4.2))) * 60) + ( int(val(substr(cTime,7,2))) )

9 changes: 7 additions & 2 deletions test/jwttest.prg
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,21 @@ AssertEquals( oJWT:Decode("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0
AssertEquals( oJWT:Decode("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6Ik1hdHRlbyBCYWNjYW4iLCJpYXQiOjE1MTYyMzkwMjIsImV4cCI6MTUxNjIzOTAyMn0.0T90m9fq8aOuiNbycTJxCf7BiQLw9xWXxe58-zV4RpY", "MySecret"), .F. )
? oJWT:GetError()

// Check internal data exposion
AssertEquals(oJWT:GetHeader()['alg'], oJWT:GetAlgorithm())
oJWT:GetHeader()['alg'] := 'dddd'
AssertEquals(oJWT:GetHeader()['alg'], oJWT:GetAlgorithm())

hb_hrbUnload( handle )

RETU NIL


function AssertEquals( uValue, uExpected )
IF uValue==uExpected
? "OK - signature verified"
? "OK - data verified"
ELSE
? "KO - invalid signature"
? "KO - invalid data"
? "Value :", uValue
? "Expected:", uExpected
ENDIF
Expand Down

0 comments on commit 8d60557

Please sign in to comment.