Forum Discussion

NetSnoopy's avatar
NetSnoopy
Icon for Cirrus rankCirrus
Apr 11, 2017

Saml token convert to jwt

Hello,

I create a iRule for convert saml token to JWT (json web token). It works well but I get a signatur error. I try many option and formats. But nothing works. I'm shure you can help me easily.

I have creat a working access Profile with saml. Bigip is SP and an external IdP. Here my iRule.

when ACCESS_ACL_ALLOWED {
        set hamacsha256 secret
       set secret_key "secret"

        get data from saml Session (APM->Manage Sessions-> Variables -> View)
       set user [ACCESS::session data get session.saml.last.nameIDValue]
       set sub [ACCESS::session data get session.saml.last.attr.name./EmployeeID]
       set nbf [ACCESS::session data get session.saml.last.validityNotBefore]
       set exp [ACCESS::session data get session.saml.last.validityNotOnOrAfter]
       set email [ACCESS::session data get session.saml.last.attr.name./identity/claims/emailaddress]
       set surname [ACCESS::session data get session.saml./Common/xyz_auth_ag.attr.name./identity/claims/surname]
       set givenname [ACCESS::session data get session.saml./Common/xyz_auth_ag.attr.name./identity/claims/givenname]
       set aud [ACCESS::session data get session.saml.last.assertionIssuer]
       set gpid [ACCESS::session data get session.saml.last.attr.name./GPID]

        Name of the cookie
       set cookie_name "xyz-JWT"

        set cookie header
       set cookie_header "[b64encode "{\r\n \"alg\": \"HS256\", \r\n \"typ\": \"JWT\"\r\n}"]"

        set cookie payload
       set cookie_payload "[b64encode "{\r\n \"user\": \"$user\",\r\n \"sub\": \"$sub\",\r\n \"nbf\": \"$nbf\",\r\n \"exp\": \"$exp\",\r\n \"email\": \"$email\",\r\n \"surname\": \"$surname\",\r\n \"givenname\": \"$givenname\",\r\n \"aud\": \"$aud\",\r\n \"gpid\": \"$gpid\"\r\n}"]"

       set cookie data for signatur
       set cookie_data [concat "[b64encode [URI::encode $cookie_header]].[b64encode [URI::encode $cookie_payload]]"]
        test some other version
       set cookie_data "[URI::encode [b64encode $cookie_header]]\".\"[URI::encode [b64encode $cookie_payload]]"
       set cookie_data "[URI::encode $cookie_header]\".\"[URI::encode $cookie_payload]]"
       set cookie_data $cookie_header"."$cookie_payload
       log local0. "cookie_data $cookie_data"

       create signatur
       set cookie_sig "[CRYPTO::sign -alg hmac-sha256 -key $secret_key $cookie_data]"
       convert signatur in some version
       set cookie_sig_b64 "[b64encode $cookie_sig]"
       set cookie_sig_b64_url "[URI::encode $cookie_sig_b64]"
       set cookie_sig_url_b64 "[b64encode $cookie_sig_url]"
       log local0. "sig_b64= $cookie_sig_b64"
       log local0. "sig_b64_url= $cookie_sig_b64_url"
       log local0. "sig_url_b64= $cookie_sig_url_b64" 

       verify signatur
       if { [CRYPTO::verify -alg hmac-sha256 -key $secret_key -signature $cookie_sig $cookie_data] } {
           log local0. "Data verified"
       }

       create full JWT
       set cookie "$cookie_header.$cookie_payload.$cookie_sig_url_b64"
       HTTP::cookie insert name $cookie_name value $cookie
       log local0. "$cookie_name $cookie"
    }

    send to client
    when HTTP_RESPONSE {
        HTTP::cookie insert name $cookie_name value $cookie
        }

If I verify the cookie with jwt.io (webseite). I get alway a signatur error. All other works. The json notation for signatur is

HMACSHA256(
      base64UrlEncode(header) + "." +
      base64UrlEncode(payload),
      secret
    ) secret base64 encoded

I think I have a mistake in format for cookie_data. In the version you can see some of my tests. How can help me?

Cheers, NetSnoopy

  • Hello,

    i found my mistake and now it's working. Here is the working iRule

    when ACCESS_ACL_ALLOWED {
         set hamacsha256 secret
        set secret_key "secret"
         get date from Saml Session
        set user [ACCESS::session data get session.saml.last.nameIDValue]
        set sub [ACCESS::session data get session.saml.last.attr.name.http://xxxx.de/EmployeeID]
        set nbf [ACCESS::session data get session.saml.last.validityNotBefore]
        set exp [ACCESS::session data get session.saml.last.validityNotOnOrAfter]
        set email [ACCESS::session data get session.saml.last.attr.name.http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress]
        set surname [ACCESS::session data get session.saml./Common/kosmos-uat_APM_Test_act_saml_auth_ag.attr.name.http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname]
        set givenname [ACCESS::session data get session.saml./Common/kosmos-uat_APM_Test_act_saml_auth_ag.attr.name.http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname]
        set aud [ACCESS::session data get session.saml.last.assertionIssuer]
        set gpid [ACCESS::session data get session.saml.last.attr.name.http://xxxx.de/xxxx-User-GPID]
        generate JWT
        set jwt_header "[b64encode "{\r\n \"alg\": \"HS256\", \r\n \"typ\": \"JWT\"\r\n}"]"
        set jwt_payload "[b64encode "{\r\n \"user\": \"$user\",\r\n \"sub\": \"$sub\",\r\n \"nbf\": \"$nbf\",\r\n \"exp\": \"$exp\",\r\n \"email\": \"$email\",\r\n \"surname\": \"$surname\",\r\n \"givenname\": \"$givenname\",\r\n \"aud\": \"$aud\",\r\n \"gpid\": \"$gpid\"\r\n}"]"
        set jwt_data "$jwt_header.$jwt_payload"
        set jwt_sig "[b64encode [CRYPTO::sign -alg hmac-sha256 -key $secret_key $jwt_data]]"
        set jwt "$jwt_header.$jwt_payload.$jwt_sig"
        log local0. "JWT $jwt"
    }
    
    when HTTP_REQUEST {
        if { [info exists jwt] }{
        HTTP::header insert Authorization "Bearer $jwt"
        }
    }
    

    In this case the JWT will only send to Server but not to Client. If you want this also to Client and the follow lines

    when HTTP_RESPONSE {
        if { [info exists jwt] }{
        HTTP::header insert Authorization "Bearer $jwt"
        }
    }
    

    I hope I can help someone with this example.

    Cheers, NetSnoopy

  • Cri's avatar
    Cri
    Icon for Nimbostratus rankNimbostratus

    Sounds good NetSnoopy!

     

    thank you very much! Only one question: you are using "nbf" as timestamp but I saw that in the JWT spec they suggest to use "iat", any reason?

     

    Cheers Pomello

     

    UPDATE: Sorry, I found the difference between iat and nbf ;)

     

    Thank you