Using Vapor to make a JWT (JSON Web Token)

I'm having trouble making a JWT with Vapor. I'm trying to make it in the format below but I'm getting errors in XCode.

{
    sub: '' + id,
    email,
    iat: Date.now() / 1000,
    iss: "https://myapp.herokuapp.com",
    "https://hasura.io/jwt/claims": {
      "x-hasura-allowed-roles": ["user"],
      "x-hasura-default-role": "user",
      "x-hasura-user-id": '' + id
    }
  };

I'm trying to follow the paylod setup in the vapor docs ( https://docs.vapor.codes/4.0/jwt/#claims )
here for reference:

// JWT payload structure.
struct TestPayload: JWTPayload {
    // Maps the longer Swift property names to the
    // shortened keys used in the JWT payload.
    enum CodingKeys: String, CodingKey {
        case subject = "sub"
        case expiration = "exp"
        case isAdmin = "admin"
    }

    // The "sub" (subject) claim identifies the principal that is the
    // subject of the JWT.
    var subject: SubjectClaim

    // The "exp" (expiration time) claim identifies the expiration time on
    // or after which the JWT MUST NOT be accepted for processing.
    var expiration: ExpirationClaim

    // Custom data.
    // If true, the user is an admin.
    var isAdmin: Bool

    // Run any additional verification logic beyond
    // signature verification here.
    // Since we have an ExpirationClaim, we will
    // call its verify method.
    func verify(using signer: JWTSigner) throws {
        try self.expiration.verifyNotExpired()
    }
}

but how do I make the other properties? For example, from the docs there's the

enum CodingKeys: String, CodingKey {
        case subject = "sub"
        case expiration = "exp"
        case isAdmin = "admin"

var subject: SubjectClaim

but how can I set up these other ones I need, particularly the key hasuraClaim since I need its value to be an object:

    enum CodingKeys: String, CodingKey {
        case subject = "sub"
        case expiration = "exp"
        case isAdmin = "admin"
    --->case iss = "iss"
    --->case hasuraClaim = "https://hasura.io/jwt/claims"

     var iss: IssuerClaim
     var hasuraClaim: HasuraClaim

Right now I'm getting the error "Type 'HasuraPayload' does not conform to protocol 'Decodable'/'Encodable' " I appreciate any help!

What does your full type look like?

Here's my whole struct, I realized it's just the hasuraClaim I need to figure out:

struct HasuraPayload: JWTPayload {
    enum CodingKeys: String, CodingKey {
        case subject = "sub"
        case expiration = "exp"
        case isAdmin = "admin"
        case iss = "iss"
        case hasuraClaim = "https://hasura.io/jwt/claims"
    }
    var subject: SubjectClaim
    var expiration: ExpirationClaim
    var isAdmin: Bool
    var iss: IssuerClaim
    var hasuraClaim: HasuraClaim

    func verify(using signer: JWTSigner) throws {
        try self.expiration.verifyNotExpired()
    }
}

struct HasuraClaim {
    ?
}

whereas when I've done this in JavaScript, the value of the hasuraClaim key is a JavaScript object

    "https://hasura.io/jwt/claims": {
      "x-hasura-allowed-roles": ["user"],
      "x-hasura-default-role": "user",
      "x-hasura-user-id": '' + id
    }

You'll need to make the HasuraClaim struct explicitly conform for Codable as well.

Thanks @Dan_Stenmark that was a simple step I overlooked (still pretty new to Swift) but I think it works now. Here's the struct I made below to match the JSON format for anyone else that needs to reference.

    "https://hasura.io/jwt/claims": {
      "x-hasura-allowed-roles": ["user"],
      "x-hasura-default-role": "user",
      "x-hasura-user-id": '' + id }

struct HasuraClaim: Codable {
    var allowedRoles: [String]
    var defaultRole: String
    var userId: String
    
    enum CodingKeys: String, CodingKey {
        case allowedRoles = "x-hasura-allowed-roles"
        case defaultRole = "x-hasura-default-role"
        case userId = "x-hasura-user-id"
    }
}
Terms of Service

Privacy Policy

Cookie Policy