Search in sources :

Example 1 with Credentials

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);
}
Also used : ClientAuthorization(it.unibo.arces.wot.sepa.commons.security.ClientAuthorization) JWTClaimsSet(com.nimbusds.jwt.JWTClaimsSet) SEPASecurityException(it.unibo.arces.wot.sepa.commons.exceptions.SEPASecurityException) SignedJWT(com.nimbusds.jwt.SignedJWT) ParseException(java.text.ParseException) JOSEException(com.nimbusds.jose.JOSEException) SimpleDateFormat(java.text.SimpleDateFormat) Date(java.util.Date) Credentials(it.unibo.arces.wot.sepa.commons.security.Credentials)

Example 2 with Credentials

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;
}
Also used : Attribute(org.apache.directory.api.ldap.model.entry.Attribute) CursorException(org.apache.directory.api.ldap.model.cursor.CursorException) SEPASecurityException(it.unibo.arces.wot.sepa.commons.exceptions.SEPASecurityException) LdapException(org.apache.directory.api.ldap.model.exception.LdapException) Credentials(it.unibo.arces.wot.sepa.commons.security.Credentials)

Example 3 with Credentials

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);
}
Also used : ClientAuthorization(it.unibo.arces.wot.sepa.commons.security.ClientAuthorization) SEPASecurityException(it.unibo.arces.wot.sepa.commons.exceptions.SEPASecurityException) SignedJWT(com.nimbusds.jwt.SignedJWT) Date(java.util.Date) BadJOSEException(com.nimbusds.jose.proc.BadJOSEException) JWTClaimsSet(com.nimbusds.jwt.JWTClaimsSet) ParseException(java.text.ParseException) JOSEException(com.nimbusds.jose.JOSEException) BadJOSEException(com.nimbusds.jose.proc.BadJOSEException) SimpleDateFormat(java.text.SimpleDateFormat) Credentials(it.unibo.arces.wot.sepa.commons.security.Credentials)

Example 4 with Credentials

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();
    }
}
Also used : DeviceIdentity(it.unibo.arces.wot.sepa.engine.dependability.authorization.identities.DeviceIdentity) ApplicationIdentity(it.unibo.arces.wot.sepa.engine.dependability.authorization.identities.ApplicationIdentity) CursorException(org.apache.directory.api.ldap.model.cursor.CursorException) SEPASecurityException(it.unibo.arces.wot.sepa.commons.exceptions.SEPASecurityException) LdapException(org.apache.directory.api.ldap.model.exception.LdapException) Credentials(it.unibo.arces.wot.sepa.commons.security.Credentials)

Example 5 with Credentials

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();
}
Also used : DeviceIdentity(it.unibo.arces.wot.sepa.engine.dependability.authorization.identities.DeviceIdentity) Scanner(java.util.Scanner) ApplicationIdentity(it.unibo.arces.wot.sepa.engine.dependability.authorization.identities.ApplicationIdentity) UserIdentity(it.unibo.arces.wot.sepa.engine.dependability.authorization.identities.UserIdentity) Console(java.io.Console) SEPASecurityException(it.unibo.arces.wot.sepa.commons.exceptions.SEPASecurityException) DigitalIdentity(it.unibo.arces.wot.sepa.engine.dependability.authorization.identities.DigitalIdentity) Credentials(it.unibo.arces.wot.sepa.commons.security.Credentials)

Aggregations

SEPASecurityException (it.unibo.arces.wot.sepa.commons.exceptions.SEPASecurityException)5 Credentials (it.unibo.arces.wot.sepa.commons.security.Credentials)5 JOSEException (com.nimbusds.jose.JOSEException)2 JWTClaimsSet (com.nimbusds.jwt.JWTClaimsSet)2 SignedJWT (com.nimbusds.jwt.SignedJWT)2 ClientAuthorization (it.unibo.arces.wot.sepa.commons.security.ClientAuthorization)2 ApplicationIdentity (it.unibo.arces.wot.sepa.engine.dependability.authorization.identities.ApplicationIdentity)2 DeviceIdentity (it.unibo.arces.wot.sepa.engine.dependability.authorization.identities.DeviceIdentity)2 ParseException (java.text.ParseException)2 SimpleDateFormat (java.text.SimpleDateFormat)2 Date (java.util.Date)2 CursorException (org.apache.directory.api.ldap.model.cursor.CursorException)2 LdapException (org.apache.directory.api.ldap.model.exception.LdapException)2 BadJOSEException (com.nimbusds.jose.proc.BadJOSEException)1 DigitalIdentity (it.unibo.arces.wot.sepa.engine.dependability.authorization.identities.DigitalIdentity)1 UserIdentity (it.unibo.arces.wot.sepa.engine.dependability.authorization.identities.UserIdentity)1 Console (java.io.Console)1 Scanner (java.util.Scanner)1 Attribute (org.apache.directory.api.ldap.model.entry.Attribute)1