Search in sources :

Example 1 with JWTResponse

use of it.unibo.arces.wot.sepa.commons.response.JWTResponse in project SEPA by arces-wot.

the class AuthorizationManager method getToken.

/**
 * POST https://wot.arces.unibo.it:8443/oauth/token
 *
 * Content-Type: application/x-www-form-urlencoded
 * Accept: application/json
 * Authorization: Basic Basic64(id:secret)
 *
 * Response example:
 * { 	"access_token": "eyJraWQiOiIyN.........",
 * 		"token_type": "bearer",
 * 		"expires_in": 3600
 * }
 *
 * In case of error, the following applies:
 * {
 * 		"code": Error code,
 * 		"body": "Error details"
 *
 * }
 */
public Response getToken(String encodedCredentials) {
    logger.debug("Get token");
    // Decode credentials
    byte[] decoded = null;
    try {
        decoded = Base64.getDecoder().decode(encodedCredentials);
    } catch (IllegalArgumentException e) {
        logger.error("Not authorized");
        return new ErrorResponse(0, HttpStatus.SC_UNAUTHORIZED, "Client not authorized");
    }
    String decodedCredentials = new String(decoded);
    String[] clientID = decodedCredentials.split(":");
    if (clientID == null) {
        logger.error("Wrong Basic authorization");
        return new ErrorResponse(0, HttpStatus.SC_UNAUTHORIZED, "Client not authorized");
    }
    if (clientID.length != 2) {
        logger.error("Wrong Basic authorization");
        return new ErrorResponse(0, HttpStatus.SC_UNAUTHORIZED, "Client not authorized");
    }
    String id = decodedCredentials.split(":")[0];
    String secret = decodedCredentials.split(":")[1];
    logger.debug("Credentials: " + id + " " + secret);
    // Verify credentials
    if (!credentials.containsKey(id)) {
        logger.error("Client id: " + id + " is not registered");
        return new ErrorResponse(0, HttpStatus.SC_UNAUTHORIZED, "Client not authorized");
    }
    if (!credentials.get(id).equals(secret)) {
        logger.error("Wrong secret: " + secret + " for client id: " + id);
        return new ErrorResponse(0, HttpStatus.SC_UNAUTHORIZED, "Client not authorized");
    }
    // Check is a token has been release for this client
    if (clientClaims.containsKey(id)) {
        // Do not return a new token if the previous one is not expired
        Date expires = clientClaims.get(id).getExpirationTime();
        Date now = new Date();
        logger.debug("Check token expiration: " + now + " > " + expires + " ?");
        if (now.before(expires)) {
            logger.warn("Token is not expired");
            return new ErrorResponse(0, HttpStatus.SC_BAD_REQUEST, "Token is not expired");
        }
    }
    // Prepare JWT with claims set
    JWTClaimsSet.Builder claimsSetBuilder = new JWTClaimsSet.Builder();
    long timestamp = new Date().getTime();
    /*
		 * 4.1.1.  "iss" (Issuer) Claim

	   The "iss" (issuer) claim identifies the principal that issued the
	   JWT.  The processing of this claim is generally application specific.
	   The "iss" value is a case-sensitive string containing a StringOrURI
	   value.  Use of this claim is OPTIONAL.*/
    claimsSetBuilder.issuer(AuthorizationManagerBeans.getIssuer());
    /* 4.1.2.  "sub" (Subject) Claim

	   The "sub" (subject) claim identifies the principal that is the
	   subject of the JWT.  The Claims in a JWT are normally statements
	   about the subject.  The subject value MUST either be scoped to be
	   locally unique in the context of the issuer or be globally unique.
	   The processing of this claim is generally application specific.  The
	   "sub" value is a case-sensitive string containing a StringOrURI
	   value.  Use of this claim is OPTIONAL.*/
    claimsSetBuilder.subject(AuthorizationManagerBeans.getSubject());
    /* 4.1.3.  "aud" (Audience) Claim

	   The "aud" (audience) claim identifies the recipients that the JWT is
	   intended for.  Each principal intended to process the JWT MUST
	   identify itself with a value in the audience claim.  If the principal
	   processing the claim does not identify itself with a value in the
	   "aud" claim when this claim is present, then the JWT MUST be
	   rejected.  In the general case, the "aud" value is an array of case-
	   sensitive strings, each containing a StringOrURI value.  In the
	   special case when the JWT has one audience, the "aud" value MAY be a
	   single case-sensitive string containing a StringOrURI value.  The
	   interpretation of audience values is generally application specific.
	   Use of this claim is OPTIONAL.*/
    ArrayList<String> audience = new ArrayList<String>();
    audience.add(AuthorizationManagerBeans.getHttpsAudience());
    audience.add(AuthorizationManagerBeans.getWssAudience());
    claimsSetBuilder.audience(audience);
    /* 4.1.4.  "exp" (Expiration Time) Claim

	   The "exp" (expiration time) claim identifies the expiration time on
	   or after which the JWT MUST NOT be accepted for processing.  The
	   processing of the "exp" claim requires that the current date/time
	   MUST be before the expiration date/time listed in the "exp" claim.
	   Implementers MAY provide for some small leeway, usually no more than
	   a few minutes, to account for clock skew.  Its value MUST be a number
	   containing a NumericDate value.  Use of this claim is OPTIONAL.*/
    claimsSetBuilder.expirationTime(new Date(timestamp + (AuthorizationManagerBeans.getTokenExpiringPeriod() * 1000)));
    /*4.1.5.  "nbf" (Not Before) Claim

	   The "nbf" (not before) claim identifies the time before which the JWT
	   MUST NOT be accepted for processing.  The processing of the "nbf"
	   claim requires that the current date/time MUST be after or equal to
	   the not-before date/time listed in the "nbf" claim.  Implementers MAY
	   provide for some small leeway, usually no more than a few minutes, to
	   account for clock skew.  Its value MUST be a number containing a
	   NumericDate value.  Use of this claim is OPTIONAL.*/
    claimsSetBuilder.notBeforeTime(new Date(timestamp - 1000));
    /* 4.1.6.  "iat" (Issued At) Claim

	   The "iat" (issued at) claim identifies the time at which the JWT was
	   issued.  This claim can be used to determine the age of the JWT.  Its
	   value MUST be a number containing a NumericDate value.  Use of this
	   claim is OPTIONAL.*/
    claimsSetBuilder.issueTime(new Date(timestamp));
    /*4.1.7.  "jti" (JWT ID) Claim

	   The "jti" (JWT ID) claim provides a unique identifier for the JWT.
	   The identifier value MUST be assigned in a manner that ensures that
	   there is a negligible probability that the same value will be
	   accidentally assigned to a different data object; if the application
	   uses multiple issuers, collisions MUST be prevented among values
	   produced by different issuers as well.  The "jti" claim can be used
	   to prevent the JWT from being replayed.  The "jti" value is a case-
	   sensitive string.  Use of this claim is OPTIONAL.*/
    claimsSetBuilder.jwtID(id + ":" + secret);
    JWTClaimsSet jwtClaims = claimsSetBuilder.build();
    // ******************************
    // Sign JWT with private RSA key
    // ******************************
    SignedJWT signedJWT;
    try {
        signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.RS256), JWTClaimsSet.parse(jwtClaims.toString()));
    } catch (ParseException e) {
        logger.error(e.getMessage());
        return new ErrorResponse(0, HttpStatus.SC_INTERNAL_SERVER_ERROR, "Error on signing JWT (1)");
    }
    try {
        signedJWT.sign(signer);
    } catch (JOSEException e) {
        logger.error(e.getMessage());
        return new ErrorResponse(0, HttpStatus.SC_INTERNAL_SERVER_ERROR, "Error on signing JWT (2)");
    }
    // Add the token to the released tokens
    clientClaims.put(id, jwtClaims);
    return new JWTResponse(signedJWT.serialize(), "bearer", AuthorizationManagerBeans.getTokenExpiringPeriod());
}
Also used : ArrayList(java.util.ArrayList) SignedJWT(com.nimbusds.jwt.SignedJWT) Date(java.util.Date) ErrorResponse(it.unibo.arces.wot.sepa.commons.response.ErrorResponse) JWTClaimsSet(com.nimbusds.jwt.JWTClaimsSet) ParseException(java.text.ParseException) JOSEException(com.nimbusds.jose.JOSEException) BadJOSEException(com.nimbusds.jose.proc.BadJOSEException) JWSHeader(com.nimbusds.jose.JWSHeader) JWTResponse(it.unibo.arces.wot.sepa.commons.response.JWTResponse)

Example 2 with JWTResponse

use of it.unibo.arces.wot.sepa.commons.response.JWTResponse in project SEPA by arces-wot.

the class AuthorizationManager method securityCheck.

private void securityCheck(String identity) {
    logger.debug("*** Security check ***");
    // Add identity
    addAuthorizedIdentity(identity);
    // Register
    logger.debug("Register: " + identity);
    Response response = register(identity);
    if (response.getClass().equals(RegistrationResponse.class)) {
        RegistrationResponse ret = (RegistrationResponse) response;
        String auth = ret.getClientId() + ":" + ret.getClientSecret();
        logger.debug("ID:SECRET=" + auth);
        // Get token
        String encodedCredentials = Base64.getEncoder().encodeToString(auth.getBytes());
        logger.debug("Authorization Basic " + encodedCredentials);
        response = getToken(encodedCredentials);
        if (response.getClass().equals(JWTResponse.class)) {
            logger.debug("Access token: " + ((JWTResponse) response).getAccessToken());
            // Validate token
            Response valid = validateToken(((JWTResponse) response).getAccessToken());
            if (!valid.getClass().equals(ErrorResponse.class))
                logger.debug("PASSED");
            else {
                ErrorResponse error = (ErrorResponse) valid;
                logger.debug("FAILED Code: " + error.getErrorCode() + "Message: " + error.getErrorMessage());
            }
        } else
            logger.debug("FAILED");
    } else
        logger.debug("FAILED");
    logger.debug("**********************");
    System.out.println("");
    // Add identity
    removeAuthorizedIdentity(identity);
}
Also used : ErrorResponse(it.unibo.arces.wot.sepa.commons.response.ErrorResponse) JWTResponse(it.unibo.arces.wot.sepa.commons.response.JWTResponse) Response(it.unibo.arces.wot.sepa.commons.response.Response) RegistrationResponse(it.unibo.arces.wot.sepa.commons.response.RegistrationResponse) RegistrationResponse(it.unibo.arces.wot.sepa.commons.response.RegistrationResponse) JWTResponse(it.unibo.arces.wot.sepa.commons.response.JWTResponse) ErrorResponse(it.unibo.arces.wot.sepa.commons.response.ErrorResponse)

Example 3 with JWTResponse

use of it.unibo.arces.wot.sepa.commons.response.JWTResponse in project SEPA by arces-wot.

the class SecurityManager method getToken.

/**
 * It requests a token to the Authorization Server. A token request should be
 * made when the current token is expired or it is the first token. If the token
 * is not expired, the "invalid_grant" error is returned.
 *
 * @param encodedCredentials the client credentials encoded using Base64
 * @return JWTResponse in case of success, ErrorResponse otherwise
 * @throws SEPASecurityException
 * @see JWTResponse
 * @see ErrorResponse
 *
 *	<pre>
 *	POST https://wot.arces.unibo.it:8443/oauth/token
 *
 *	Content-Type: application/x-www-form-urlencoded
 *	Accept: application/json
 *	Authorization: Basic Basic64(id:secret)
 *
 *	Response example:
 *	{
 *	"access_token": "eyJraWQiOiIyN.........",
 *	"token_type": "bearer",
 *	"expires_in": 3600
 *	}
 *
 *	 Error response example:
 *	 {
 *	   "error":"Unless specified otherwise see RFC6749. Otherwise, this is specific of the SPARQL 1.1 SE Protocol",
 *	   "error_description":"Unless specified otherwise, see RFC6749. Otherwise, this is specific to the SPARQL 1.1 SE Protocol", (OPTIONAL)
 *	   "status_code" : the HTTP status code (should be 400 for all Oauth 2.0 errors).
 *	 }
 *
 *	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>
 */
public synchronized Response getToken(String encodedCredentials) {
    logger.debug("GET TOKEN");
    // Decode credentials
    byte[] decoded = null;
    try {
        decoded = Base64.getDecoder().decode(encodedCredentials);
    } catch (IllegalArgumentException e) {
        logger.error("Not authorized");
        return new ErrorResponse(HttpStatus.SC_UNAUTHORIZED, "invalid_request", e.getMessage());
    }
    // Parse credentials
    String decodedCredentials = new String(decoded);
    // BUG SOLVED. The clientID may contain ":"
    // e.g., urn:epc:id:gid:0.1.410D23751450344850323220
    int marker = decodedCredentials.lastIndexOf(":");
    if (marker == -1) {
        logger.error("Wrong Basic authorization");
        return new ErrorResponse(HttpStatus.SC_UNAUTHORIZED, "invalid_client", "Delimiter ':' is missing. Wrong credentials format: " + decodedCredentials);
    }
    // String[] clientID = decodedCredentials.split(":");
    // if (clientID == null) {
    // logger.error("Wrong Basic authorization");
    // return new ErrorResponse(HttpStatus.SC_UNAUTHORIZED, "invalid_client",
    // "Client id not found: " + decodedCredentials);
    // }
    // if (clientID.length != 2) {
    // logger.error("Wrong Basic authorization");
    // return new ErrorResponse(HttpStatus.SC_UNAUTHORIZED, "invalid_client",
    // "Wrong credentials: " + decodedCredentials);
    // }
    // String id = decodedCredentials.split(":")[0];
    // String secret = decodedCredentials.split(":")[1];
    String id = decodedCredentials.substring(0, marker);
    String secret = decodedCredentials.substring(marker + 1);
    logger.debug("Credentials: " + id + " " + secret);
    // Verify credentials
    try {
        if (!containsCredentials(id)) {
            logger.error("Client id: " + id + " is not registered");
            return new ErrorResponse(HttpStatus.SC_BAD_REQUEST, "unauthorized_client", "Client identity " + id + " not found");
        }
    } catch (SEPASecurityException e2) {
        return new ErrorResponse(HttpStatus.SC_BAD_REQUEST, "unauthorized_client", e2.getMessage());
    }
    try {
        if (!checkCredentials(id, secret)) {
            logger.error("Wrong secret: " + secret + " for client id: " + id);
            return new ErrorResponse(HttpStatus.SC_BAD_REQUEST, "unauthorized_client", "Wrong credentials for identity " + id);
        }
    } catch (SEPASecurityException e2) {
        return new ErrorResponse(HttpStatus.SC_BAD_REQUEST, "unauthorized_client", e2.getMessage());
    }
    // Prepare JWT with claims set
    JWTClaimsSet.Builder claimsSetBuilder = new JWTClaimsSet.Builder();
    Date now = new Date();
    // Check if the token is not expired
    try {
        if (containsJwt(id)) {
            Date expiring = getTokenExpiringDate(id);
            long expiringUnixSeconds = (expiring.getTime() / 1000) * 1000;
            long nowUnixSeconds = (now.getTime() / 1000) * 1000;
            long delta = expiringUnixSeconds - nowUnixSeconds;
            // Expires if major than current time
            logger.debug("ID: " + id + " ==> Token will expire in: " + delta + " ms");
            if (delta > 0) {
                logger.warn("Token is NOT EXPIRED. Return the current token.");
                JWTResponse jwt = null;
                try {
                    jwt = new JWTResponse(getJwt(id));
                } catch (SEPASecurityException e) {
                    logger.error(e.getMessage());
                    return new ErrorResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR, "security_error", "Failed to retrieve expiring period");
                }
                return jwt;
            }
            logger.debug("Token is EXPIRED. Release a fresh token.");
        }
    } catch (SEPASecurityException e2) {
        return new ErrorResponse(HttpStatus.SC_BAD_REQUEST, "security_error", e2.getMessage());
    }
    /*
		 * 4.1.1. "iss" (Issuer) Claim
		 * 
		 * The "iss" (issuer) claim identifies the principal that issued the JWT. The
		 * processing of this claim is generally application specific. The "iss" value
		 * is a case-sensitive string containing a StringOrURI value. Use of this claim
		 * is OPTIONAL.
		 */
    // try {
    // claimsSetBuilder.issuer(auth.getIssuer());
    // } catch (SEPASecurityException e1) {
    // return new ErrorResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR, "invalid_issuer",
    // e1.getMessage());
    // }
    /*
		 * 4.1.2. "sub" (Subject) Claim
		 * 
		 * The "sub" (subject) claim identifies the principal that is the subject of the
		 * JWT. The Claims in a JWT are normally statements about the subject. The
		 * subject value MUST either be scoped to be locally unique in the context of
		 * the issuer or be globally unique. The processing of this claim is generally
		 * application specific. The "sub" value is a case-sensitive string containing a
		 * StringOrURI value. Use of this claim is OPTIONAL.
		 */
    claimsSetBuilder.subject(id);
    /*
		 * 4.1.3. "aud" (Audience) Claim
		 * 
		 * The "aud" (audience) claim identifies the recipients that the JWT is intended
		 * for. Each principal intended to process the JWT MUST identify itself with a
		 * value in the audience claim. If the principal processing the claim does not
		 * identify itself with a value in the "aud" claim when this claim is present,
		 * then the JWT MUST be rejected. In the general case, the "aud" value is an
		 * array of case- sensitive strings, each containing a StringOrURI value. In the
		 * special case when the JWT has one audience, the "aud" value MAY be a single
		 * case-sensitive string containing a StringOrURI value. The interpretation of
		 * audience values is generally application specific. Use of this claim is
		 * OPTIONAL.
		 */
    // ArrayList<String> audience = new ArrayList<String>();
    // try {
    // audience.add(auth.getHttpsAudience());
    // } catch (SEPASecurityException e1) {
    // return new ErrorResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR, "invalid_https_audience",
    // e1.getMessage());
    // }
    // try {
    // audience.add(auth.getWssAudience());
    // } catch (SEPASecurityException e1) {
    // return new ErrorResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR, "invalid_wss_audience",
    // e1.getMessage());
    // }
    // claimsSetBuilder.audience(audience);
    /*
		 * 4.1.4. "exp" (Expiration Time) Claim
		 * 
		 * The "exp" (expiration time) claim identifies the expiration time on or after
		 * which the JWT MUST NOT be accepted for processing. The processing of the
		 * "exp" claim requires that the current date/time MUST be before the expiration
		 * date/time listed in the "exp" claim. Implementers MAY provide for some small
		 * leeway, usually no more than a few minutes, to account for clock skew. Its
		 * value MUST be a number containing a NumericDate value. Use of this claim is
		 * OPTIONAL.
		 */
    /*
		 * NOTICE: this date is serialized as SECONDS from UNIX time NOT milliseconds!
		 */
    // Define the expiration time
    Date expires;
    try {
        expires = new Date(now.getTime() + (getTokenExpiringPeriod(id) * 1000));
    } catch (SEPASecurityException e1) {
        logger.error(e1.getMessage());
        return new ErrorResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR, "security_error", "Failed to retrieve expiring period");
    }
    claimsSetBuilder.expirationTime(expires);
    /*
		 * 4.1.5. "nbf" (Not Before) Claim
		 * 
		 * The "nbf" (not before) claim identifies the time before which the JWT MUST
		 * NOT be accepted for processing. The processing of the "nbf" claim requires
		 * that the current date/time MUST be after or equal to the not-before date/time
		 * listed in the "nbf" claim. Implementers MAY provide for some small leeway,
		 * usually no more than a few minutes, to account for clock skew. Its value MUST
		 * be a number containing a NumericDate value. Use of this claim is OPTIONAL.
		 */
    // claimsSetBuilder.notBeforeTime(before);
    /*
		 * 4.1.6. "iat" (Issued At) Claim
		 * 
		 * The "iat" (issued at) claim identifies the time at which the JWT was issued.
		 * This claim can be used to determine the age of the JWT. Its value MUST be a
		 * number containing a NumericDate value. Use of this claim is OPTIONAL.
		 */
    claimsSetBuilder.issueTime(now);
    /*
		 * 4.1.7. "jti" (JWT ID) Claim
		 * 
		 * The "jti" (JWT ID) claim provides a unique identifier for the JWT. The
		 * identifier value MUST be assigned in a manner that ensures that there is a
		 * negligible probability that the same value will be accidentally assigned to a
		 * different data object; if the application uses multiple issuers, collisions
		 * MUST be prevented among values produced by different issuers as well. The
		 * "jti" claim can be used to prevent the JWT from being replayed. The "jti"
		 * value is a case- sensitive string. Use of this claim is OPTIONAL.
		 */
    // claimsSetBuilder.jwtID(id);
    JWTClaimsSet jwtClaims = claimsSetBuilder.build();
    // ******************************
    // Sign JWT with private RSA key
    // ******************************
    SignedJWT signedJWT;
    try {
        signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.RS256), JWTClaimsSet.parse(jwtClaims.toString()));
    } catch (ParseException e) {
        logger.error(e.getMessage());
        return new ErrorResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR, "parsing_exception", "ParseException: " + e.getMessage());
    }
    try {
        signedJWT.sign(signer);
    } catch (JOSEException e) {
        logger.error(e.getMessage());
        return new ErrorResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR, "sign_exception", "JOSEException: " + e.getMessage());
    }
    // Add the token to the released tokens
    try {
        addJwt(id, signedJWT);
    } catch (SEPASecurityException e1) {
        logger.error(e1.getMessage());
        return new ErrorResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR, "security_error", e1.getMessage());
    }
    JWTResponse jwt = null;
    try {
        jwt = new JWTResponse(signedJWT);
    } catch (SEPASecurityException e) {
        logger.error(e.getMessage());
        return new ErrorResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR, "security_error", "Failed to retrieve expiring period");
    }
    logger.debug("Released token: " + jwt);
    return jwt;
}
Also used : SEPASecurityException(it.unibo.arces.wot.sepa.commons.exceptions.SEPASecurityException) SignedJWT(com.nimbusds.jwt.SignedJWT) Date(java.util.Date) ErrorResponse(it.unibo.arces.wot.sepa.commons.response.ErrorResponse) JWTClaimsSet(com.nimbusds.jwt.JWTClaimsSet) ParseException(java.text.ParseException) JOSEException(com.nimbusds.jose.JOSEException) BadJOSEException(com.nimbusds.jose.proc.BadJOSEException) JWSHeader(com.nimbusds.jose.JWSHeader) JWTResponse(it.unibo.arces.wot.sepa.commons.response.JWTResponse)

Example 4 with JWTResponse

use of it.unibo.arces.wot.sepa.commons.response.JWTResponse in project SEPA by arces-wot.

the class SecurityManager method securityCheck.

public void securityCheck(String identity) throws SEPASecurityException {
    logger.info("*** Security check ***");
    // Add identity
    addAuthorizedIdentity(new ApplicationIdentity(identity));
    // Register
    Response response = register(identity);
    if (response.getClass().equals(RegistrationResponse.class)) {
        RegistrationResponse ret = (RegistrationResponse) response;
        String basicAuth = ret.getClientId() + ":" + ret.getClientSecret();
        // Get token
        String encodedCredentials = Base64.getEncoder().encodeToString(basicAuth.getBytes());
        logger.debug("Authorization Basic " + encodedCredentials);
        response = getToken(encodedCredentials);
        if (response.getClass().equals(JWTResponse.class)) {
            logger.debug("Access token: " + ((JWTResponse) response).getAccessToken());
            // Validate token
            ClientAuthorization authRet = validateToken(((JWTResponse) response).getAccessToken());
            if (authRet.isAuthorized()) {
                removeCredentials(new ApplicationIdentity(ret.getClientId()));
                removeJwt(ret.getClientId());
                logger.info("*** PASSED ***");
            } else {
                logger.error(authRet.getError());
                logger.info("*** FAILED ***");
            }
        } else {
            logger.debug(response.toString());
            logger.info("*** FAILED ***");
        }
    } else {
        logger.debug(response.toString());
        logger.info("*** FAILED ***");
        // Remove identity
        removeAuthorizedIdentity(identity);
    }
    System.out.println("");
}
Also used : Response(it.unibo.arces.wot.sepa.commons.response.Response) RegistrationResponse(it.unibo.arces.wot.sepa.commons.response.RegistrationResponse) ErrorResponse(it.unibo.arces.wot.sepa.commons.response.ErrorResponse) JWTResponse(it.unibo.arces.wot.sepa.commons.response.JWTResponse) ClientAuthorization(it.unibo.arces.wot.sepa.commons.security.ClientAuthorization) ApplicationIdentity(it.unibo.arces.wot.sepa.engine.dependability.authorization.identities.ApplicationIdentity) RegistrationResponse(it.unibo.arces.wot.sepa.commons.response.RegistrationResponse) JWTResponse(it.unibo.arces.wot.sepa.commons.response.JWTResponse)

Example 5 with JWTResponse

use of it.unibo.arces.wot.sepa.commons.response.JWTResponse in project SEPA by arces-wot.

the class SPARQL11Protocol method executeRequest.

/*
	 * http://hc.apache.org/httpcomponents-client-4.5.x/tutorial/html/fundamentals.
	 * html#d5e279
	 * 
	 * 1.5. Exception handling
	 * 
	 * HTTP protocol processors can throw two types of exceptions:
	 * 
	 * 1) java.io.IOException in case of an I/O failure such as socket timeout or an
	 * socket reset 2) HttpException that signals an HTTP failure such as a
	 * violation of the HTTP protocol.
	 * 
	 * Usually I/O errors are considered non-fatal and recoverable, whereas HTTP
	 * protocol errors are considered fatal and cannot be automatically recovered
	 * from. Please note that HttpClient implementations re-throw HttpExceptions as
	 * ClientProtocolException, which is a subclass of java.io.IOException. This
	 * enables the users of HttpClient to handle both I/O errors and protocol
	 * violations from a single catch clause.
	 */
/*
	 * {"error":"IOException","status_code":500,
	 * "error_description":"Connect to mml.arces.unibo.it:8666 [mml.arces.unibo.it/137.204.143.19] failed: Operation timed out"
	 * }
	 * 
	 * extended by java.io.IOException extended by java.net.SocketException extended
	 * by java.net.ConnectException extended by
	 * org.apache.http.conn.HttpHostConnectException
	 * 
	 */
private Response executeRequest(HttpUriRequest req, Request request) {
    CloseableHttpResponse httpResponse = null;
    HttpEntity responseEntity = null;
    int responseCode = 0;
    String responseBody = null;
    ErrorResponse errorResponse = null;
    try {
        // Execute HTTP request
        logger.trace(req.toString() + " " + request.toString() + " (timeout: " + request.getTimeout() + " ms) ");
        long start = Timings.getTime();
        httpResponse = httpClient.execute(req);
        long stop = Timings.getTime();
        if (request.getClass().equals(UpdateRequest.class))
            Timings.log("HTTP_UPDATE_TIME", start, stop);
        else
            Timings.log("HTTP_QUERY_TIME", start, stop);
        // Status code
        responseCode = httpResponse.getStatusLine().getStatusCode();
        // Body
        responseEntity = httpResponse.getEntity();
        responseBody = EntityUtils.toString(responseEntity, Charset.forName("UTF-8"));
        logger.trace(String.format("Response code: %d", responseCode));
        EntityUtils.consume(responseEntity);
    } catch (Exception e) {
        errorResponse = new ErrorResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR, e.getClass().getName(), e.getMessage());
        // Considered as *** TIMEOUTS ***
        if (e instanceof HttpHostConnectException || e instanceof SocketTimeoutException || e instanceof ConnectTimeoutException || e instanceof RequestAbortedException)
            errorResponse = new ErrorResponse(HttpStatus.SC_REQUEST_TIMEOUT, e.getClass().getName(), e.getMessage() + " [timeout: " + request.getTimeout() + " ms retry: " + request.getNRetry() + "]");
    } finally {
        try {
            if (httpResponse != null)
                httpResponse.close();
        } catch (IOException e) {
            logger.error(e.getMessage());
            return new ErrorResponse(HttpStatus.SC_INTERNAL_SERVER_ERROR, "IOException", e.getMessage());
        }
        responseEntity = null;
    }
    if (responseCode >= 400 && errorResponse == null) {
        // http://mml.arces.unibo.it/TR/sparql11-se-protocol.html#ErrorResponses
        try {
            JsonObject ret = new JsonParser().parse(responseBody).getAsJsonObject();
            errorResponse = new ErrorResponse(ret.get("status_code").getAsInt(), ret.get("error").getAsString(), ret.get("error_description").getAsString());
        } catch (Exception e) {
            // E.g. parsing response from a "common" SPARQL endpoint
            logger.warn(e.getMessage() + " response code:" + responseCode + " response body: " + responseBody);
            if (responseBody.equals(""))
                responseBody = httpResponse.toString();
            errorResponse = new ErrorResponse(responseCode, "sparql11_endpoint", responseBody);
        }
    }
    if (errorResponse != null) {
        logger.error(errorResponse + " Token expired: " + errorResponse.isTokenExpiredError() + " Security manager: " + (sm != null) + " nRetry: " + request.getNRetry());
        // TOKEN EXPIRED
        if (errorResponse.isTokenExpiredError()) {
            try {
                logger.info("Refresh token");
                Response ret = sm.refreshToken();
                if (ret.isError())
                    return ret;
                JWTResponse token = (JWTResponse) ret;
                logger.debug(token.getAccessToken());
                req.setHeader("Authorization", token.getTokenType() + " " + token.getAccessToken());
            // request.setAuthorizationHeader(token.getTokenType()+"
            // "+token.getAccessToken());
            } catch (SEPAPropertiesException | SEPASecurityException e) {
                logger.error("Failed to refresh token. " + e.getMessage());
                return errorResponse;
            }
            return executeRequest(req, request);
        } else // TIMEOUT
        if (errorResponse.isTimeout() && request.getNRetry() > 0) {
            logger.warn(errorResponse);
            logger.warn("*** TIMEOUT RETRY " + request.getNRetry() + " ***");
            request.retry();
            return executeRequest(req, request);
        }
        return errorResponse;
    }
    return (request.getClass().equals(UpdateRequest.class) ? new UpdateResponse(responseBody) : new QueryResponse(responseBody));
}
Also used : HttpEntity(org.apache.http.HttpEntity) SEPAPropertiesException(it.unibo.arces.wot.sepa.commons.exceptions.SEPAPropertiesException) JsonObject(com.google.gson.JsonObject) SEPASecurityException(it.unibo.arces.wot.sepa.commons.exceptions.SEPASecurityException) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) RequestAbortedException(org.apache.http.impl.execchain.RequestAbortedException) HttpHostConnectException(org.apache.http.conn.HttpHostConnectException) SEPAPropertiesException(it.unibo.arces.wot.sepa.commons.exceptions.SEPAPropertiesException) ConnectTimeoutException(org.apache.http.conn.ConnectTimeoutException) SocketTimeoutException(java.net.SocketTimeoutException) SEPASecurityException(it.unibo.arces.wot.sepa.commons.exceptions.SEPASecurityException) IOException(java.io.IOException) UnsupportedEncodingException(java.io.UnsupportedEncodingException) ErrorResponse(it.unibo.arces.wot.sepa.commons.response.ErrorResponse) Response(it.unibo.arces.wot.sepa.commons.response.Response) CloseableHttpResponse(org.apache.http.client.methods.CloseableHttpResponse) QueryResponse(it.unibo.arces.wot.sepa.commons.response.QueryResponse) UpdateResponse(it.unibo.arces.wot.sepa.commons.response.UpdateResponse) ErrorResponse(it.unibo.arces.wot.sepa.commons.response.ErrorResponse) JWTResponse(it.unibo.arces.wot.sepa.commons.response.JWTResponse) UpdateResponse(it.unibo.arces.wot.sepa.commons.response.UpdateResponse) SocketTimeoutException(java.net.SocketTimeoutException) QueryResponse(it.unibo.arces.wot.sepa.commons.response.QueryResponse) CloseableHttpResponse(org.apache.http.client.methods.CloseableHttpResponse) HttpHostConnectException(org.apache.http.conn.HttpHostConnectException) RequestAbortedException(org.apache.http.impl.execchain.RequestAbortedException) ConnectTimeoutException(org.apache.http.conn.ConnectTimeoutException) JsonParser(com.google.gson.JsonParser) JWTResponse(it.unibo.arces.wot.sepa.commons.response.JWTResponse)

Aggregations

ErrorResponse (it.unibo.arces.wot.sepa.commons.response.ErrorResponse)11 JWTResponse (it.unibo.arces.wot.sepa.commons.response.JWTResponse)11 SEPASecurityException (it.unibo.arces.wot.sepa.commons.exceptions.SEPASecurityException)6 Response (it.unibo.arces.wot.sepa.commons.response.Response)5 Date (java.util.Date)5 JsonObject (com.google.gson.JsonObject)4 JsonParser (com.google.gson.JsonParser)4 RegistrationResponse (it.unibo.arces.wot.sepa.commons.response.RegistrationResponse)4 JOSEException (com.nimbusds.jose.JOSEException)3 BadJOSEException (com.nimbusds.jose.proc.BadJOSEException)3 JWTClaimsSet (com.nimbusds.jwt.JWTClaimsSet)3 SignedJWT (com.nimbusds.jwt.SignedJWT)3 SEPAPropertiesException (it.unibo.arces.wot.sepa.commons.exceptions.SEPAPropertiesException)3 IOException (java.io.IOException)3 UnsupportedEncodingException (java.io.UnsupportedEncodingException)3 URISyntaxException (java.net.URISyntaxException)3 ParseException (java.text.ParseException)3 HttpEntity (org.apache.http.HttpEntity)3 CloseableHttpResponse (org.apache.http.client.methods.CloseableHttpResponse)3 JWSHeader (com.nimbusds.jose.JWSHeader)2