0

I've been asked to generate a token depending on the username that is asking for it. Now I'm creating a token just with a single subject but I don't know how to change the subject dinamically before creating the token depending on the body of the request.

This is what I've done so far to generate a token with a single subject: The service class:

@Component
@RequiredArgsConstructor
public class JwtService {

    @Value("${issuer}")
    private String issuer;
    @Value("${kid}")
    private String keyId;
    @Value("#{'${audience}'.split(',')}")
    private List<String> audiences;
    @Value("#{'${subject}'.split(',')}")
    private List<String> subject;

    private final JwtKeyProvider jwtKeyProvider;

    public String generateToken() throws JoseException {
       
        JwtClaims claims = new JwtClaims();
        claims.setIssuer(issuer);
        claims.setAudience(Lists.newArrayList(audiences));
        claims.setExpirationTimeMinutesInTheFuture(60);
        claims.setJwtId(keyId);
        claims.setIssuedAtToNow();
        claims.setNotBeforeMinutesInThePast(0);
        claims.setSubject(subject);
     
        JsonWebSignature jws = new JsonWebSignature();

        jws.setPayload(claims.toJson());

        jws.setHeader("typ", "JWT");

        jws.setKey(jwtKeyProvider.getPrivateKey());
        jws.setKeyIdHeaderValue(keyId);
        jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
        
        String jwt = jws.getCompactSerialization();
        return jwt;
    }
}

And the controller:

@RestController
@RequiredArgsConstructor
public class JWTController {

    private final JwtService jwtService;

    @PostMapping("/getToken")
    public ResponseEntity getJwt(@RequestBody JwtRequest request) throws JoseException {
            return ResponseEntity.ok(
                    JwtResponse.builder()
                            .token(jwtService.generateToken())
                            .build()
            );
    }
}

I could do it doing like this:

 @PostMapping("/getToken")
        public ResponseEntity getJwt(@RequestBody JwtRequest request) throws JoseException {
                return ResponseEntity.ok(
                        JwtResponse.builder()
                                .token(jwtService.generateToken(request.getUsername()))
                                .build()
                );
        }
    }

But I don't want to send any parameters in the generateToken function as I would have to change a lot of code then.

To resume I want to assign to the subject the value of the username that is sent in the body. So is there a way in the JwtService class to receive that username and set as the subject after?

Thanks in advance!

DiegoMG
  • 383
  • 1
  • 4
  • 18

1 Answers1

0

First you need to put whitelist=user1,user2 in your application.properties, because sometimes names might trigger as system variables (for example username does)

Then in JWTController you need to check if not user equals, but contains in list

    @Value("#{'${whitelist}'.split(',')}")
    private List<String> whitelist;

    @PostMapping("/getToken")
    public ResponseEntity<?> getJwt(@RequestBody JwtRequest request) throws JoseException {
        if(whitelist.contains(request.username())) {
            return ResponseEntity.ok(
                    JwtResponse.builder()
                            .token(jwtService.generateToken(request.username()))
                            .build()
            );
        } else {
            return ResponseEntity.ok("Invalid username");
        }
    }

In your JWTService you need to set JWT Subject to username which passed through whitelist

claims.setSubject(username);

And finally you need to do JSON request to server

{
    "username": "user2"
}
Georglider
  • 52
  • 6