I am able to verify the JWT Token, by manually setting each individual request with the bearer token, but whenever I set them to inherit auth from parent, it returns Unauthorized, it says clearly that it's taking the auth from the name of the collection, and I've set the collection to the bearer token.
Here is the JWTMiddleware:
func JWTMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
authHeader := strings.Split(r.Header.Get("Authorization"), "Bearer ")
if len(authHeader) != 2 {
fmt.Println("Malformed token")
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte("Malformed Token"))
} else {
jwtToken := authHeader[1]
token, err := jwt.Parse(jwtToken, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
}
return []byte(os.Getenv("JWT_SECRET")), nil
})
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
ctx := context.WithValue(r.Context(), "props", claims)
next.ServeHTTP(w, r.WithContext(ctx))
} else {
fmt.Println(err)
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte("Unauthorized"))
}
}
})
}
Here is how the token is generated:
func generateJWT() (JWTToken, error) {
signingKey := []byte(os.Getenv("JWT_SECRET"))
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
"exp": time.Now().Add(time.Hour * 1 * 1).Unix(),
})
tokenString, err := token.SignedString(signingKey)
return JWTToken{tokenString}, err
}
Here is how my routes are structured:
var Routes = router.RoutePrefix{
"/generate",
[]router.Route{
router.Route{
"gen_token",
"GET",
"",
gen_token,
false,
},
router.Route{
"testToken",
"GET",
"/test",
testToken,
true,
},
},
}
I am considering setting a global variable that I can set as the token for testing purposes, what would the solution be?
Related
I have an application that has only the POST method, and every time I make a request in that application, it saves some data for me in my postgres database..
locally my application works properly, but when I deploy and try to test it through the azure function app it returns a 500 error and says that it was not possible to store my information in the database..
here are some code snippets
go code:
func (h handler) sendgridWeb(c *gin.Context) {
data, _ := io.ReadAll(c.Request.Body)
var ListaEventoEmail []Email
if err := json.Unmarshal(data, &ListaEventoEmail); err != nil {
log.Fatal("Error when unrealizing content contained in Body")
}
for _, email := range ListaEventoEmail {
email.SgMessageId = email.SgMessageId[:strings.IndexByte(email.SgMessageId, '.')]
//-- PROCESSED --//
if email.Event == "processed" {
inserting := `insert into email (email_destinatario, enviado, id_sendgrid) values ($1, $2, $3)`
_, err := h.DB.Exec(inserting, email.Email, true, email.SgMessageId)
if err != nil {
log.Fatal("Error inserting data into email table")
}
}
//-- DELIVERED --//
if email.Event == "delivered" {
_, err := h.DB.Exec(`UPDATE email SET recebido=true WHERE id_sendgrid=$1`, email.SgMessageId)
if err != nil {
log.Fatal("Error when uploading email with DELIVERED event")
}
//-- OPEN --//
} else if email.Event == "open" {
_, err := h.DB.Exec(`UPDATE email SET recebido=true, aberto=true WHERE id_sendgrid=$1`, email.SgMessageId)
if err != nil {
log.Fatal("Error when uploading email with OPEN event")
}
} else if email.Event == "click" {
_, err := h.DB.Exec(`UPDATE email SET click = click + 1 WHERE id_sendgrid=$1`, email.SgMessageId)
if err != nil {
log.Fatal("Error when uploading email with CLICK event")
}
}
my connection string is stored in a toml file..
connection string:
# filename: config.toml
[postgres]
host = "132.168.0.22"
port = 5432
user = "postgres"
password = "ivaneteJC"
dbname = "webhook"
you can see that, in the HOST field I put my IP (fictitious ip)..
in my logic, when deploying to azure, my connection string should point to my machine, so I used the ip, thus performing the necessary operations on my database, but this does not happen .. when making a POST request by the postman (using the endpoint that o was provided when deploying to the azure function app, I get a 500 error and in my logs I get the message "Error inserting data into the email table" which is an error described in my go app, I believe I made a mistake somewhere that has a connection to the database, can someone help me?
function.json:
{
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}
host.json:
{
"version": "2.0",
"logging": {
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"excludedTypes": "Request"
}
}
},
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[3.*, 4.0.0)"
},
"customHandler": {
"description": {
"defaultExecutablePath": "main.exe",
"workingDirectory": "",
"arguments": []
},
"enableForwardingHttpRequest": true
}
}
local.settings.json:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "custom"
}
}
I did as mentioned in a comment, I treated the error in an original way .. and the following error appeared:
"connectex: An attempt was made to access a socket in a way prohibited by its access permissions."
db:
type handler struct {
DB *sql.DB
}
type PostgreConfig struct {
Host string
Port int
User string
Password string
Dbname string
}
type MyConfig struct {
Postgres *PostgreConfig
}
func Init() *sql.DB {
doc, err := os.ReadFile("config.toml")
if err != nil {
panic(err)
}
var cfg MyConfig
err = toml.Unmarshal(doc, &cfg)
if err != nil {
panic(err)
}
stringConn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", cfg.Postgres.Host, cfg.Postgres.Port, cfg.Postgres.User, cfg.Postgres.Password, cfg.Postgres.Dbname)
db, err := sql.Open("postgres", stringConn)
if err != nil {
log.Fatal("Erro ao realizar conexão")
} else {
fmt.Println("Conectado")
}
fmt.Println(stringConn)
db.Ping()
return db
}
func OpenDB(DB *sql.DB) handler {
return handler{DB}
}
I want to be able to return a 401 on JWT token expiry (which I believe is the correct response?) but it returns a 403 no matter what
here is where I tell swagger tools to use my bearer token verification logic:
swaggerTools.initializeMiddleware(swaggerObject, (middleware) => {
// Interpret Swagger resources and attach metadata to request - must be first in swagger-tools middleware chain
app.use(middleware.swaggerMetadata());
//enable cors
app.use(
cors({
methods: ["GET", "POST", "PATCH", "DELETE"],
origin: "*",
preflightContinue: false,
optionsSuccessStatus: 204,
})
);
//verify bearer token for protected apis
app.use(
middleware.swaggerSecurity({
Bearer: (req, authOrSecDef, token, callback) =>
//if this is a protected endpoint then token is verified to allow or deny access
securityService.verifyToken(
req,
authOrSecDef,
token,
callback
),
})
);
and here is my verifyToken function..
verifyToken: (req, authOrSecDef, token, callback) => {
const sendError = (error) => {
if (error) {
if (error.name === "TokenExpiredError") {
return new Problem(401, error.message);
}
} else {
return new Problem(403);
}
};
if (token && token.toLowerCase().indexOf("bearer ") === 0) {
var tokenString = token.split(" ")[1];
let completeDecodedToken = jwt.decode(tokenString, { complete: true });
if (!completeDecodedToken) {
return callback(sendError());
}
//use header.kid to find correct cognito jwk to use
let jwk = jwks.keys.find(
(jwk) => jwk.kid == completeDecodedToken.header.kid
);
if (!jwk) {
//must have passed in a token obtained from somewhere else
return callback(sendError());
}
const pem = jwkToPem(jwk);
jwt.verify(
tokenString,
pem,
{ algorithms: ["RS256"] },
(verificationError, decodedToken) => {
if (verificationError === null) {
// check if the issuer matches
var issuerMatch =
decodedToken.iss ===
`https://cognito-idp.${process.env.AWS_REGION}.amazonaws.com/${process.env.COGNITO_USER_POOL_ID}`;
if (issuerMatch) {
//add the token to the request so that we
//can access it downstream in endpoint if we need
req.auth = decodedToken;
req.tokenString = tokenString;
//if there is no error, just return null in the callback
return callback(null);
} else {
console.error("Issuer did not match");
//return the error in the callback if there is one
return callback(sendError());
}
} else {
//return the error in the callback if the JWT was not verified
return callback(sendError(verificationError));
}
}
);
} else {
return callback(sendError());
}
},
but actually when I look in the swagger-tools source (swagger-security.js) I only see 403 in there.. any advice ?
You see 403 always because that is the else part and your error object is null, If you are able to debug then you can console log the error
Also your assumption is that error is returned from below line, which is highly likely wrong because error is null.
//return the error in the callback if the JWT was not verified
return callback(sendError(verificationError));
In my opinion, error is returned from
else {
return callback(sendError());
}
If that is the case then you can send your custom "UnauthorizedError" object from the desired place.
I want to add a mongo user to the mongodb. I tried the following:
import (
"context"
"fmt"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"log"
"os"
"time"
)
type User struct {
User string `json:"user"`
Db string `json:"db"`
Roles []Role`json:"roles"`
PasswordDigestor string `json:"passwordDigestor"`
Pwd string `json:"pwd"`
}
type Role struct {
Role string `json:"role"`
Db string `json:"db"`
}
func CreateUser() {
client, err := mongo.NewClient(options.Client().ApplyURI(fmt.Sprintf("mongodb://%s:%s#%s/test?authSource=%s&replicaSet=%s",
mongoConf.user,mongoConf.password,mongoConf.host,mongoConf.authDB,mongoConf.replicaset)))
if err != nil {
log.Fatal(err)
}
ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
err = client.Connect(ctx)
if err != nil {
log.Fatal(err)
}
defer client.Disconnect(ctx)
//pass := password(8)
pass := "Test123!"
if _, err = client.Database("admin").Collection("system.users").InsertOne(context.Background(),User{
User: "test",
Db: "admin",
Roles: []Role{
{Role: "readWriteAnyDatabase",
Db: "admin",
},
},
PasswordDigestor: "server",
Pwd: pass,
}); err != nil {
panic(err)
}
}
But that is not working. With the shell it is not a problem with db.createUser(). But how I'm supposed to do this with go? I was able to list all users from the system.users table. When I insert a user like this into the database its working without problems, but it is not possible to log in with the created user.
EDIT:
runnint db.createUser:
function (userObj, writeConcern) {
var name = userObj["user"];
var cmdObj = {createUser: name};
cmdObj = Object.extend(cmdObj, userObj);
delete cmdObj["user"];
this._modifyCommandToDigestPasswordIfNecessary(cmdObj, name);
cmdObj["writeConcern"] = writeConcern ? writeConcern : _defaultWriteConcern;
var res = this.runCommand(cmdObj);
if (res.ok) {
print("Successfully added user: " + getUserObjString(userObj));
return;
}
if (res.errmsg == "no such cmd: createUser") {
throw Error("'createUser' command not found. This is most likely because you are " +
"talking to an old (pre v2.6) MongoDB server");
}
if (res.errmsg == "timeout") {
throw Error("timed out while waiting for user authentication to replicate - " +
"database will not be fully secured until replication finishes");
}
throw _getErrorWithCode(res, "couldn't add user: " + res.errmsg);
}
Thanks to #Joe I could solve the problem running the following command:
r := client.Database(dbName).RunCommand(context.Background(),bson.D{{"createUser", userName},
{"pwd", pass}, {"roles", []bson.M{{"role": roleName,"db":roldeDB}}}})
if r.Err() != nil {
panic(r.Err())
}
I want to create a function to process anykind of forms.
I want it to be able to handle any kind of data types.
Im trying to use a interface to do this task.
type Person struct {
name string
lastName string
}
func HTMLForm(c *gin.Context) {
var f Person
c.ShouldBind(&f)
c.JSON(http.StatusOK, f)
}
// with this function i get the correct info
// output: {"name":"john","lastName":"snow"}
func HTMLForm(c *gin.Context) {
var f interface{}
c.ShouldBind(&f)
c.JSON(http.StatusOK, f)
}
// when i use the interface to make it usefull for any type of that
// i get null
// output: null
func HTMLForm(c *gin.Context) {
var f interface{}
ShouldBindJSON(f)
c.JSON(http.StatusOK, f)
}
// output: null
I want to get, with the interface, the same output I get with "Person" data type.
// Another example of how i am using f
type Login struct {
User string
Password string
}
func main() {
router := gin.Default()
router.POST("/loginForm", func(c *gin.Context) {
var f interface{}
if err := c.ShouldBind(&f); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, f)
})
// Listen and serve on 0.0.0.0:8080
router.Run(":8080")
}
// output: null
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Update
I want to try to explain my problem better.
Maybe this update it's more clear.
// Golang code
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
// Binding from JSON
type Login struct {
User string `form:"user" json:"user" xml:"user" binding:"required"`
Password string `form:"password" json:"password" xml:"password" binding:"required"`
}
func main() {
router := gin.Default()
router.LoadHTMLGlob("templates/*")
router.GET("/login", GetLogin)
router.POST("/loginJSON", PostJSONForm)
router.POST("/loginXML", PostXMLForm)
router.POST("/loginForm", PostHTMLForm)
/*
sudo lsof -n -i :8080
kill -9 <PID>
*/
router.Run(":8080")
}
func GetLogin(c *gin.Context) {
c.HTML(http.StatusOK, "login.tmpl", nil)
}
// Example for binding JSON ({"user": "manu", "password": "123"})
// curl -v -X POST http://localhost:8080/loginJSON -H 'content-type: application/json' '{ "user": "manu", "password"="123" }'
func PostJSONForm(c *gin.Context) {
//var json Login
var json interface{}
//var form map[string]interface{}
if err := c.ShouldBindJSON(&json); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
/*
if json.User != "manu" || json.Password != "123" {
c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
return
}
c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
*/
c.JSON(http.StatusOK, "json")
c.JSON(http.StatusOK, json)
}
// Example for binding XML (
// <?xml version="1.0" encoding="UTF-8"?>
// <root>
// <user>user</user>
// <password>123</password>
// </root>)
// curl -v -X POST http://localhost:8080/loginXML -H 'content-type: application/json' -d '{ "user": "manu", "password"="123" }'
func PostXMLForm(c *gin.Context) {
//var xml Login
var xml interface{}
//var form map[string]interface{}
if err := c.ShouldBindXML(&xml); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
/*
if xml.User != "manu" || xml.Password != "123" {
c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
return
}
c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
*/
c.JSON(http.StatusOK, "xml")
c.JSON(http.StatusOK, xml)
}
// Example for binding a HTML form (user=manu&password=123)
// curl -v -X POST http://localhost:8080/loginForm -H 'content-type: application/json' -d '{ "user": "manu", "password":"123" }'
func PostHTMLForm(c *gin.Context) {
//var form Login
var form interface{}
//var form map[string]interface{}
// This will infer what binder to use depending on the content-type header.
if err := c.ShouldBind(&form); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
/*
if form.User != "manu" || form.Password != "123" {
c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"})
return
}
c.JSON(http.StatusOK, gin.H{"status": "you are logged in"})
*/
c.JSON(http.StatusOK, "html")
c.JSON(http.StatusOK, form)
}
//Template
<h1>Login</h1>
<form action="/loginForm" method="POST">
<label>user:</label><br>
<input type="text" name="user"><br>
<label>password:</label><br>
<input type="text" name="password"><br>
<input type="submit">
</form>
I have tried all this different variations. Just one works, I explain more below.
It works perfect if I use "var form Login" instead of "var from interface{}". But I need it to be able to work with any data type, so I need it to work with interface{}.
I have had a "successful" output, just with one of interface{} tries:
$ curl -X POST http://localhost:8080/loginForm -H 'content-type: application/json' -d '{ "user": "manu", "password":"123" }'
output:"html"{"password":"123","user":"manu"}
But when I use it on a HTML form, on a browser, with that template I posted i get:
output: "html"null
Im not sure if what I get (point 3) its really a sucessfull output. When I use the Login var, it works fine, with curl and brower, the output it's inverted:
$ curl -X POST http://localhost:8080/loginForm -H 'content-type: application/json' -d '{ "user": "manu", "password":"123" }'
ouput:"html"{"user":"manu","password":"123"}
This is all information I could get till now.
This version of last answer worked with html form and curl json submission.
package main
import (
"net/http"
"fmt"
"github.com/gin-gonic/gin"
)
// Binding from JSON
type Login struct {
User string `form:"user" json:"user" xml:"user" binding:"required"`
Password string `form:"password" json:"password" xml:"password" binding:"required"`
}
func main() {
router := gin.Default()
router.LoadHTMLGlob("templates/*")
router.GET("/login", func(c *gin.Context) {
c.HTML(http.StatusOK, "login.tmpl", nil)
})
// Example for binding a HTML form (user=manu&password=123)
router.POST("/loginForm", func(c *gin.Context) {
var form Login
// This will infer what binder to use depending on the content-type header.
if err := c.ShouldBind(&form); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, form)
})
// Listen and serve on 0.0.0.0:8080
router.Run(":8080")
}
And templates/login.tmpl:
<html>
<body>
<h1>Login</h1>
<form action="/loginForm" method="POST">
<label>user:</label><br>
<input type="text" name="user"><br>
<label>password:</label><br>
<input type="text" name="password"><br>
<input type="submit">
</form>
</body>
</html>
Do you try to use ShouldBindJSON? Because it has to know which type your want to be
ShouldBind checks the Content-Type to select a binding engine automatically, Depending the "Content-Type" header different bindings are used:
from source code of gin:
// ShouldBindJSON is a shortcut for c.ShouldBindWith(obj, binding.JSON).
func (c *Context) ShouldBindJSON(obj interface{}) error {
return c.ShouldBindWith(obj, binding.JSON)
}
Update:
In your case, it work for me ?
router := gin.Default()
router.POST("/loginForm", func(c *gin.Context) {
var f interface{}
if err := c.ShouldBindJSON(&f); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
log.Print(f)
c.JSON(http.StatusOK, f)
})
// Listen and serve on 0.0.0.0:8080
router.Run(":8080")
Example login
curl -X POST -H "Content-Type: application/json" \
--data '{"username":"xyz","password":"xyz"}' localhost:8080/loginForm
Result
[GIN-debug] POST /loginForm --> main.main.func1 (3 handlers)
[GIN-debug] Listening and serving HTTP on :8080
map[password:xyz username:xyz]
[GIN] 2019/04/23 - 10:07:00 | 200 | 239.317µs | ::1 | POST /loginForm
//////////////////////////////////
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
// Binding from JSON
type Login struct {
User string `form:"user" json:"user" xml:"user" binding:"required"`
Password string `form:"password" json:"password" xml:"password" binding:"required"`
}
func main() {
router := gin.Default()
router.LoadHTMLGlob("templates/*")
router.GET("/login", func(c *gin.Context) {
c.HTML(http.StatusOK, "login.tmpl", nil)
})
// Example for binding a HTML form (user=manu&password=123)
router.POST("/loginForm", func(c *gin.Context) {
var form interface{}
// This will infer what binder to use depending on the content-type header.
if err := c.ShouldBind(&form); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, form)
})
// Listen and serve on 0.0.0.0:8080
router.Run(":8080")
}
//the template
<h1>Login</h1>
<form action="/loginForm" method="POST">
<label>user:</label><br>
<input type="text" name="user"><br>
<label>password:</label><br>
<input type="text" name="password"><br>
<input type="submit">
</form>
//I get null when I use de HTML from, when I try the curl command, it works
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()
})
}
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{}.
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/
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);