7

I'm using go-swagger with BearerAuth using JWT tokens. Along with the actual token I'm receiving claims which include such data as username.

How can I access claims in api.ItemsCreateItemHandler function below?

package restapi

func configureAPI(api *operations.MyAPI) http.Handler {
    api.BearerAuth = func(token string) (interface{}, error) {
        jwtToken := strings.Replace(token, "Bearer ", "", -1)
        // skipped token verification

        claims, _ := parsedToken.Claims.(jwt.MapClaims)
  }

  api.ItemsCreateItemHandler = items.CreateItemHandlerFunc(func(params items.CreateItemParams, principal interface{}) middleware.Responder {
    // FIXME: Here I need to be able to access JWT claims
    if err := createItem(params.Body, claims); err != nil {
            return nil // handle error
        }
        return items.NewCreateItemCreated()
    })
}
Maklaus
  • 538
  • 2
  • 16
  • 37

3 Answers3

1

First your BearerAuth implementation is meant to return the security principal (which can be your claims in this case), this value will subsequently be passed to your handler in the principal argument.

So the way to do this is:

package restapi

import (
    jwt "github.com/dgrijalva/jwt-go"
    // ...
)

func configureAPI(api *operations.MyAPI) http.Handler {
    api.BearerAuth = func(token string) (interface{}, error) {
        jwtToken := strings.Replace(token, "Bearer ", "", -1)
        // skipped token verification
        claims, _ := parsedToken.Claims.(jwt.MapClaims)
        return claims, nil
    }

    api.ItemsCreateItemHandler = items.CreateItemHandlerFunc(func(params items.CreateItemParams, principal interface{}) middleware.Responder {
        claims, ok := principal.(jwt.MapClaims)
        if !ok {
            // handle error
        }
        if err := createItem(params.Body, claims); err != nil {
            return nil // handle error
        }
        return items.NewCreateItemCreated()
    })
}

You can make this less cumbersome by using the --principal jwt.MapClaims option to swagger generate so that it uses this type for the claims instead of interface{}.

Ezequiel Muns
  • 7,492
  • 33
  • 57
-1

A JWT is made up of 3 parts, split by punctuation - the token itself is base64 encoded.

For example, heres a token from https://jwt.io/

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

You'll want to split and decode, you're after the second part which contains the payload which is just plain JSON.

So in psuedo code it'll look something like;

json = Base64Decode(split(".", yourData)[1])

You'll see more concrete example at https://jwt.io/

HenrikM
  • 427
  • 6
  • 19
-1

I have a class that store token and contains parse method:

import io.jsonwebtoken.*;

 @AllArgsConstructor
public class RawAccessJwtToken implements JwtToken {

    private String token;

    @Override
    public String getToken() {
        return token;
    }

    public Jws<Claims> parseClaims(String signingKey) {
        try {
            return Jwts.parser().setSigningKey(signingKey).parseClaimsJws(this.token);
        } catch (UnsupportedJwtException | MalformedJwtException | IllegalArgumentException e) {
            throw  new BadCredentialsException("Invalid JWT token: " + e);
        } catch (ExpiredJwtException expiredException){
            throw new JwtExpiredTokenException(this, "JWT Token expired", expiredException);
        }
    }
}

With that class I can extract my users role:

 Jws<Claims> claimsJws = token.parseClaims(signingKey);

        List<String> scopes = claimsJws.getBody().get("scopes",
                 List.class);
Muhammed Ozdogan
  • 5,341
  • 8
  • 32
  • 53