use of it.unibo.arces.wot.sepa.commons.security.Credentials in project SEPA by arces-wot.
the class KeyCloakSecurityManager method validateToken.
/**
* Requesting Party Token
*
* If you want to validate these tokens without a call to the remote introspection endpoint, you can decode the RPT and query for its validity locally.
* Once you decode the token, you can also use the permissions within the token to enforce authorization decisions.
*
* This is essentially what the policy enforcers do. Be sure to:
* 1) Validate the signature of the RPT (based on the realm’s public key)
* 2) Query for token validity based on its exp, iat, and aud claims
*
* The claim "preferred_username" is used to identify the user
*/
@Override
public synchronized ClientAuthorization validateToken(String accessToken) {
logger.log(Level.getLevel("oauth"), "VALIDATE TOKEN");
// Parse token
SignedJWT signedJWT = null;
try {
signedJWT = SignedJWT.parse(accessToken);
} catch (ParseException e) {
logger.log(Level.getLevel("oauth"), e.getMessage());
return new ClientAuthorization("invalid_request", "ParseException: " + e.getMessage());
}
// Verify token
try {
if (!signedJWT.verify(verifier)) {
logger.log(Level.getLevel("oauth"), "Signed JWT not verified");
return new ClientAuthorization("invalid_grant", "Signed JWT not verified");
}
} catch (JOSEException e) {
logger.log(Level.getLevel("oauth"), e.getMessage());
return new ClientAuthorization("invalid_grant", "JOSEException: " + e.getMessage());
}
String uid;
// Process token (validate)
JWTClaimsSet claimsSet = null;
try {
claimsSet = signedJWT.getJWTClaimsSet();
logger.log(Level.getLevel("oauth"), claimsSet);
// Get client credentials for accessing the SPARQL endpoint
uid = claimsSet.getStringClaim("username");
if (uid == null) {
logger.log(Level.getLevel("oauth"), "<username> claim is null. Look for <preferred_username>");
uid = claimsSet.getStringClaim("preferred_username");
if (uid == null) {
logger.log(Level.getLevel("oauth"), "USER ID not found...");
return new ClientAuthorization("invalid_grant", "Username claim not found");
}
}
logger.log(Level.getLevel("oauth"), "Subject: " + claimsSet.getSubject());
logger.log(Level.getLevel("oauth"), "Issuer: " + claimsSet.getIssuer());
logger.log(Level.getLevel("oauth"), "Username: " + uid);
} catch (ParseException e) {
logger.error(e.getMessage());
return new ClientAuthorization("invalid_grant", "ParseException. " + e.getMessage());
}
// Check token expiration (an "invalid_grant" error is raised if the token is
// expired)
Date now = new Date();
long nowUnixSeconds = (now.getTime() / 1000) * 1000;
Date expiring = claimsSet.getExpirationTime();
Date notBefore = claimsSet.getNotBeforeTime();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
if (expiring.getTime() - nowUnixSeconds < 0) {
logger.log(Level.getLevel("oauth"), "Token is expired: " + sdf.format(claimsSet.getExpirationTime()) + " < " + sdf.format(new Date(nowUnixSeconds)));
return new ClientAuthorization("invalid_grant", "Token issued at " + sdf.format(claimsSet.getIssueTime()) + " is expired: " + sdf.format(claimsSet.getExpirationTime()) + " < " + sdf.format(now));
}
if (notBefore != null && nowUnixSeconds < notBefore.getTime()) {
logger.log(Level.getLevel("oauth"), "Token can not be used before: " + claimsSet.getNotBeforeTime());
return new ClientAuthorization("invalid_grant", "Token can not be used before: " + claimsSet.getNotBeforeTime());
}
Credentials cred = null;
try {
cred = getEndpointCredentials(uid);
logger.log(Level.getLevel("oauth"), "Endpoint credentials: " + cred);
} catch (SEPASecurityException e) {
logger.log(Level.getLevel("oauth"), "Failed to retrieve credentials (" + uid + ")");
return new ClientAuthorization("invalid_grant", "Failed to get credentials (" + uid + ")");
}
return new ClientAuthorization(cred);
}
use of it.unibo.arces.wot.sepa.commons.security.Credentials in project SEPA by arces-wot.
the class LdapSecurityManager method getEndpointCredentials.
@Override
public Credentials getEndpointCredentials(String uid) throws SEPASecurityException {
bind();
try {
logger.log(Level.getLevel("ldap"), "[LDAP] getEndpointCredentials Base DN: " + "uid=" + uid + ",ou=credentials," + prop.getBase());
cursor = ldap.search("uid=" + uid + ",ou=credentials," + prop.getBase(), "(objectclass=*)", SearchScope.OBJECT, "*");
if (cursor.next()) {
Attribute attr = cursor.get().get("javaSerializedData");
if (attr != null) {
byte[] cred = attr.getBytes();
Credentials auth = Credentials.deserialize(cred);
// TODO: WARNING. PRINTING CREDENTIALS just for debugging purposes
logger.debug("[LDAP] " + auth);
return auth;
}
}
} catch (LdapException | CursorException e) {
logger.error("[LDAP] LdapException|CursorException : " + e.getMessage());
throw new SEPASecurityException(e.getMessage());
} finally {
unbind();
}
return null;
}
use of it.unibo.arces.wot.sepa.commons.security.Credentials in project SEPA by arces-wot.
the class SecurityManager method validateToken.
/**
* Operation when receiving a request at a protected endpoint
*
* <pre>
* Specific to HTTP request:
* 1. Check if the request contains an Authorization header.
* 2. Check if the request contains an Authorization: Bearer-header with non-null/empty contents
* 3. Check if the value of the Authorization: Bearer-header is a JWT object
*
* Token validation:
* 4. Check if the JWT object is signed
* 5. Check if the signature of the JWT object is valid. This is to be checked with AS public signature verification key
* 6. Check the contents of the JWT object
* 7. Check if the value of "iss" is https://wot.arces.unibo.it:8443/oauth/token
* 8. Check if the value of "aud" contains https://wot.arces.unibo.it:8443/sparql
* 9. Accept the request as well as "sub" as the originator of the request and process it as usual
*
* Respond with 401 if not
*
* According to RFC6749, the error member can assume the following values: invalid_request, invalid_client, invalid_grant, unauthorized_client, unsupported_grant_type, invalid_scope.
*
* invalid_request
* The request is missing a required parameter, includes an
* unsupported parameter value (other than grant type),
* repeats a parameter, includes multiple credentials,
* utilizes more than one mechanism for authenticating the
* client, or is otherwise malformed.
*
* invalid_client
* Client authentication failed (e.g., unknown client, no
* client authentication included, or unsupported
* authentication method). The authorization server MAY
* return an HTTP 401 (Unauthorized) status code to indicate
* which HTTP authentication schemes are supported. If the
* client attempted to authenticate via the "Authorization"
* request header field, the authorization server MUST
* respond with an HTTP 401 (Unauthorized) status code and
* include the "WWW-Authenticate" response header field
* matching the authentication scheme used by the client.
*
* invalid_grant
* The provided authorization grant (e.g., authorization
* code, resource owner credentials) or refresh token is
* invalid, expired, revoked, does not match the redirection
* URI used in the authorization request, or was issued to
* another client.
*
* unauthorized_client
* The authenticated client is not authorized to use this
* authorization grant type.
*
* unsupported_grant_type
* The authorization grant type is not supported by the
* authorization server.
*
* </pre>
*
* @param accessToken the JWT token to be validate according to points 4-6
*/
public synchronized ClientAuthorization validateToken(String accessToken) {
logger.debug("VALIDATE TOKEN");
// Parse token
SignedJWT signedJWT = null;
try {
signedJWT = SignedJWT.parse(accessToken);
} catch (ParseException e) {
logger.error(e.getMessage());
return new ClientAuthorization("invalid_request", "ParseException: " + e.getMessage());
}
// Verify token
try {
if (!signedJWT.verify(verifier)) {
logger.error("Signed JWT not verified");
return new ClientAuthorization("invalid_grant", "Signed JWT not verified");
}
} catch (JOSEException e) {
logger.error(e.getMessage());
return new ClientAuthorization("invalid_grant", "JOSEException: " + e.getMessage());
}
// Process token (validate)
JWTClaimsSet claimsSet = null;
try {
claimsSet = jwtProcessor.process(accessToken, new SEPASecurityContext());
} catch (ParseException e) {
logger.error(e.getMessage());
return new ClientAuthorization("invalid_grant", "ParseException. " + e.getMessage());
} catch (BadJOSEException e) {
logger.error(e.getMessage());
return new ClientAuthorization("invalid_grant", "BadJOSEException. " + e.getMessage());
} catch (JOSEException e) {
logger.error(e.getMessage());
return new ClientAuthorization("invalid_grant", "JOSEException. " + e.getMessage());
}
// Check token expiration (an "invalid_grant" error is raised if the token is expired)
Date now = new Date();
long nowUnixSeconds = (now.getTime() / 1000) * 1000;
Date expiring = claimsSet.getExpirationTime();
Date notBefore = claimsSet.getNotBeforeTime();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
if (expiring.getTime() - nowUnixSeconds < 0) {
logger.warn("Token is expired: " + sdf.format(claimsSet.getExpirationTime()) + " < " + sdf.format(new Date(nowUnixSeconds)));
return new ClientAuthorization("invalid_grant", "Token issued at " + sdf.format(claimsSet.getIssueTime()) + " is expired: " + sdf.format(claimsSet.getExpirationTime()) + " < " + sdf.format(now));
}
if (notBefore != null && nowUnixSeconds < notBefore.getTime()) {
logger.warn("Token can not be used before: " + claimsSet.getNotBeforeTime());
return new ClientAuthorization("invalid_grant", "Token can not be used before: " + claimsSet.getNotBeforeTime());
}
// Get client credentials for accessing the SPARQL endpoint
String id = claimsSet.getSubject();
logger.debug("Get credentials for uid: " + id);
Credentials cred = null;
try {
cred = getEndpointCredentials(id);
logger.trace(cred);
} catch (SEPASecurityException e) {
logger.error("Failed to retrieve credentials (" + id + ")");
return new ClientAuthorization("invalid_grant", "Failed to get credentials (" + id + ")");
}
return new ClientAuthorization(cred);
}
use of it.unibo.arces.wot.sepa.commons.security.Credentials in project SEPA by arces-wot.
the class LdapSecurityManager method getIdentity.
@Override
public DigitalIdentity getIdentity(String uid) throws SEPASecurityException {
logger.log(Level.getLevel("ldap"), "[LDAP] getIdentity " + uid + " uid=" + uid + ",ou=authorizedIdentities," + prop.getBase(), "(objectclass=*)");
bind();
try {
cursor = ldap.search("uid=" + uid + ",ou=authorizedIdentities," + prop.getBase(), "(objectclass=*)", SearchScope.OBJECT, "*");
if (!cursor.next())
throw new SEPASecurityException("uid=" + uid + ",ou=authorizedIndentities," + prop.getBase() + " NOT FOUND");
// SPARQL endpoint credentials are stored as Java Serialized Object
Credentials credentials = null;
if (cursor.get().contains("objectClass", "javaSerializedObject")) {
credentials = Credentials.deserialize(cursor.get().get("javaSerializedData").getBytes());
}
if (cursor.get().contains("objectClass", "device"))
return new DeviceIdentity(uid, credentials);
else if (cursor.get().contains("objectClass", "applicationProcess"))
return new ApplicationIdentity(uid, credentials);
else
throw new SEPASecurityException("Digital identity class NOT FOUND");
} catch (LdapException | CursorException e) {
logger.error("[LDAP] getIdentity exception " + e.getMessage());
throw new SEPASecurityException("getIdentity exception " + e.getMessage());
} finally {
unbind();
}
}
use of it.unibo.arces.wot.sepa.commons.security.Credentials in project SEPA by arces-wot.
the class ACLManager method main.
public static void main(String[] args) {
Console console = System.console();
Scanner in = new Scanner(System.in);
System.out.println("********************");
System.out.println("* SEPA ACL Manager *");
System.out.println("********************");
LdapSecurityManager ldap;
String line;
while (true) {
System.out.print("Host (return for default: localhost): ");
line = in.nextLine();
if (!line.equals(""))
host = line;
System.out.print("Port (return for default: 10389): ");
line = in.nextLine();
if (!line.equals(""))
port = Integer.parseInt(line);
System.out.print("Base (return for default: dc=sepatest,dc=com): ");
line = in.nextLine();
if (!line.equals(""))
base = line;
System.out.print("User (return for default: uid=admin,ou=system): ");
line = in.nextLine();
if (!line.equals(""))
user = line;
if (console != null)
pwd = new String(console.readPassword("Password (default: secret):"));
else {
System.out.print("Password (default: secret):");
line = in.nextLine();
if (!line.equals(""))
pwd = line;
}
try {
ldap = new LdapSecurityManager(JKSUtil.getSSLContext("sepa.jks", "sepa2020"), JKSUtil.getRSAKey("sepa.jks", "sepa2020", "jwt", "sepa2020"), new LdapProperties(host, port, base, null, user, pwd, false));
} catch (SEPASecurityException e2) {
System.out.println(e2.getMessage());
continue;
}
break;
}
System.out.println("Connected to LDAP!");
System.out.println("Set SPARQL endpoint credentials");
System.out.print("User (return for default: SEPATest):");
line = in.nextLine();
String user = "SEPATest";
if (!line.equals(""))
user = line;
if (console != null)
pwd = new String(console.readPassword("Password (default: SEPATest):"));
else {
System.out.print("Password (default: SEPATest):");
line = in.nextLine();
pwd = line;
}
while (true) {
System.out.println("Available actions: ");
System.out.println("1 - Register application");
System.out.println("2 - Register device");
System.out.println("3 - Register user");
System.out.println("4 - Change SPARQL endpoint credentials");
System.out.println("5 - Show SPARQL endpoint credentials");
System.out.println("6 - Exit");
System.out.print("Select: ");
String action = in.nextLine();
if (action.equals("6"))
break;
DigitalIdentity identity = null;
String client_secret = null;
switch(action) {
case "1":
System.out.print("UID: ");
String uid = in.nextLine();
identity = new ApplicationIdentity(uid, new Credentials(user, pwd));
break;
case "2":
System.out.print("UID: ");
uid = in.nextLine();
identity = new DeviceIdentity(uid, new Credentials(user, pwd));
break;
case "3":
System.out.print("Name: ");
String cn = in.nextLine();
System.out.print("Surname: ");
String sn = in.nextLine();
System.out.print("email: ");
uid = in.nextLine();
identity = new UserIdentity(uid, cn, sn, new Credentials(user, pwd));
if (console != null)
client_secret = new String(console.readPassword("Password: "));
else {
System.out.print("Password: ");
line = in.nextLine();
client_secret = line;
}
break;
case "4":
System.out.println("Change SPARQL endpoint credentials");
System.out.print("User: ");
user = in.nextLine();
System.out.print("Password: ");
pwd = in.nextLine();
continue;
case "5":
System.out.println("SPARQL endpoint credentials");
System.out.println("---------------------------");
System.out.println("User: <" + user + ">");
System.out.println("Password: <" + pwd + ">");
System.out.println("---------------------------");
continue;
default:
System.out.println("Wrong selection: " + action);
continue;
}
try {
if (action.equals("3")) {
if (!ldap.storeCredentials(identity, client_secret)) {
System.out.print("Entity already exists! Do you want to replace it? (y/n): ");
if (in.nextLine().toLowerCase().startsWith("n"))
continue;
ldap.removeCredentials(identity);
ldap.storeCredentials(identity, client_secret);
}
} else
ldap.addAuthorizedIdentity(identity);
} catch (SEPASecurityException e) {
try {
if (!action.equals("4")) {
System.out.print("Entity already exists! Do you want to replace it? (y/n): ");
if (in.nextLine().toLowerCase().startsWith("n"))
continue;
ldap.removeAuthorizedIdentity(identity.getUid());
ldap.addAuthorizedIdentity(identity);
} else {
System.out.println("Failed to create entity: " + identity);
continue;
}
} catch (SEPASecurityException e1) {
System.out.println("Entity creation failed");
continue;
}
}
System.out.println("Entity created!");
}
in.close();
}
Aggregations