blob: 1881db83357fe7cb164735326f93d98010c2a816 [file] [log] [blame]
package de.ids_mannheim.korap.config;
import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jose.crypto.MACVerifier;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
import de.ids_mannheim.korap.exceptions.KustvaktException;
import de.ids_mannheim.korap.exceptions.StatusCodes;
import de.ids_mannheim.korap.user.GenericUserData;
import de.ids_mannheim.korap.user.TokenContext;
import de.ids_mannheim.korap.user.User;
import de.ids_mannheim.korap.user.Userdata;
import de.ids_mannheim.korap.utils.TimeUtils;
import org.joda.time.DateTime;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.ParseException;
import java.util.Map;
/**
* @author hanl
* @date 19/05/2014
*/
public class JWTSigner {
private URL issuer;
private JWSSigner signer;
private JWSVerifier verifier;
private final int defaultttl;
public JWTSigner (final byte[] secret, URL issuer, final int defaulttl) {
this.issuer = issuer;
this.signer = new MACSigner(secret);
this.verifier = new MACVerifier(secret);
this.defaultttl = defaulttl;
}
public JWTSigner (final byte[] secret, String issuer)
throws MalformedURLException {
this(secret, new URL(issuer), 72 * 60 * 60);
}
public SignedJWT createJWT (User user, Map<String, Object> attr) {
return signContent(user, attr, defaultttl);
}
public SignedJWT signContent (User user, Map<String, Object> attr, int ttl) {
String scopes;
JWTClaimsSet cs = new JWTClaimsSet();
cs.setIssuerClaim(this.issuer.toString());
if ((scopes = (String) attr.get(Attributes.SCOPES)) != null) {
Userdata data = new GenericUserData();
data.readQuietly(attr, false);
Scopes claims = Scopes.mapScopes(scopes, data);
cs.setCustomClaims(claims.toMap());
}
cs.setSubjectClaim(user.getUsername());
if (attr.get(Attributes.CLIENT_ID) != null)
cs.setAudienceClaim(new String[] { (String) attr
.get(Attributes.CLIENT_ID) });
cs.setExpirationTimeClaim(TimeUtils.getNow().plusSeconds(ttl)
.getMillis());
SignedJWT signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.HS256),
cs);
try {
signedJWT.sign(signer);
}
catch (JOSEException e) {
return null;
}
return signedJWT;
}
/**
* @param username
* @param json
* @return
*/
public SignedJWT signContent (String username, String userclient,
String json, int ttl) {
JWTClaimsSet cs = new JWTClaimsSet();
cs.setSubjectClaim(username);
if (!json.isEmpty())
cs.setCustomClaim("data", json);
cs.setExpirationTimeClaim(TimeUtils.getNow().plusSeconds(ttl)
.getMillis());
cs.setIssuerClaim(this.issuer.toString());
if (!userclient.isEmpty())
cs.setCustomClaim("userip", userclient);
SignedJWT signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.HS256),
cs);
try {
signedJWT.sign(signer);
}
catch (JOSEException e) {
return null;
}
return signedJWT;
}
public SignedJWT signContent (String username, String userclient,
String json) {
return signContent(username, userclient, json, defaultttl);
}
public SignedJWT createSignedToken (String username) {
return createSignedToken(username, defaultttl);
}
// add client info
public SignedJWT createSignedToken (String username, int ttl) {
return signContent(username, "", "", ttl);
}
public SignedJWT verifyToken (String token) throws KustvaktException {
SignedJWT client;
try {
client = SignedJWT.parse(token);
if (!client.verify(verifier))
throw new KustvaktException(StatusCodes.REQUEST_INVALID);
if (!new DateTime(client.getJWTClaimsSet().getExpirationTimeClaim())
.isAfterNow())
throw new KustvaktException(StatusCodes.EXPIRED,
"authentication token is expired", token);
}
catch (ParseException | JOSEException e) {
//todo: message or entity, how to treat??!
throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT,
"token could not be verified", token);
}
return client;
}
// does not care about expiration times
public String retrieveContent (String signedContent)
throws KustvaktException {
SignedJWT jwt;
try {
jwt = SignedJWT.parse(signedContent);
if (!jwt.verify(verifier))
throw new KustvaktException(StatusCodes.REQUEST_INVALID,
"token invalid", signedContent);
return (String) jwt.getJWTClaimsSet().getCustomClaim("data");
}
catch (ParseException | JOSEException e) {
return null;
}
}
public TokenContext getTokenContext (String idtoken) throws ParseException,
JOSEException, KustvaktException {
SignedJWT signedJWT = verifyToken(idtoken);
TokenContext c = new TokenContext();
c.setUsername(signedJWT.getJWTClaimsSet().getSubjectClaim());
if (signedJWT.getJWTClaimsSet().getAudienceClaim() != null)
c.addContextParameter(Attributes.CLIENT_ID, signedJWT
.getJWTClaimsSet().getAudienceClaim()[0]);
c.setExpirationTime(signedJWT.getJWTClaimsSet()
.getExpirationTimeClaim());
c.setToken(idtoken);
c.addParams(signedJWT.getJWTClaimsSet().getCustomClaims());
return c;
}
}