I am using Java as back end to communicate with AWS Cognito. I am able to login, logout, create users, sign out and other functions. I am also able to verify an access token by following this link:
But I want to verify if a user is logged in or not.
In JAVA, is there a isLoggedin() function that returns a boolean or is there a way to see if the token is revoked? These functions exist for Android and iOS but what about JAVA.
I thought this verifies if the token is active, but it only verifies if the token is in the right format:
// This parses token to JWT.
JWT jwtparser = JWTParser.parse(accessToken);
String JWTissuer = jwtparser.getJWTClaimsSet().getIssuer();
JWSHeader header = (JWSHeader) jwtparser.getHeader();
Object token_use = jwtparser.getJWTClaimsSet().getClaim("token_use");
Object exp = jwtparser.getJWTClaimsSet().getClaim("iat");
Date expirationDate = jwtparser.getJWTClaimsSet().getExpirationTime();
// Read in JSON Key file saved somewhere safe
File file = new File("jwks.json");
String content = FileUtils.readFileToString(file, "utf-8");
JSONObject JsonObjects = new JSONObject(content);
JSONArray keysArray = JsonObjects.getJSONArray("keys");
JSONObject keyString = (JSONObject) keysArray.get(1);
if (header.getKeyID().equals(keyString.get("kid")) && token_use.toString().equals("access") && JWTissuer.equals("https://cognito-idp.us-west-2.amazonaws.com/us-west-2_xxxxxxx")) {
return true;
} else { return false; }
I want to see if a user is logged in. I have not found an appropriate method to do so.
Mahalo
I found a work around:
public boolean isLoggedin(String accessToken) {
GetUserRequest request = new GetUserRequest();
request.withAccessToken(accessToken);
AWSCognitoIdentityProviderClientBuilder builder =
AWSCognitoIdentityProviderClientBuilder.standard();
builder.withRegion("us-west-2");
AWSCognitoIdentityProvider cognitoCreate = builder.build();
GetUserResult result = cognitoCreate.getUser(request);
try {
System.out.println("success");
return true;
} catch (Exception e) {
e.getMessage();
return false;
}
}
Related
Every amazon API has it's own token which you have to set to next request. But with aws log api I got infinity loop:
public class Some {
public static void main (String[] args) {
final GetLogEventsRequest request = new GetLogEventsRequest()
.withLogGroupName("myGroup")
.withLogStreamName("myStrean");
final AWSLogs awsLogs = AWSLogsClientBuilder.defaultClient();
Collection<OutputLogEvent> result = new ArrayList<>();
GetLogEventsResult response = null;
do {
response = awsLogs.getLogEvents(request);
result.addAll(response.getEvents());
request.withNextToken(response.getNextBackwardToken());
} while (response.getNextBackwardToken() != null);
}
}
From documentation:
nextBackwardToken
The token for the next set of items in the backward direction. The token expires after 24 hours. This token will never be null. If you have reached the end of the stream, it will return the same token you passed in.
So it can not be null like LastEvaluatedKey when you scan dynamodb:
Map<String, AttributeValue> lastKeyEvaluated = null;
do {
ScanRequest scanRequest = new ScanRequest()
.withTableName("ProductCatalog")
.withLimit(10)
.withExclusiveStartKey(lastKeyEvaluated);
ScanResult result = client.scan(scanRequest);
for (Map<String, AttributeValue> item : result.getItems()){
printItem(item);
}
lastKeyEvaluated = result.getLastEvaluatedKey();
} while (lastKeyEvaluated != null);
So and what I should pass to request.withNextToken if we speak about log api??? And if nextBackwardToken (and nextForwardToken too) can not be null - how to detect that I receive the last response from amazon???
The documentation which you've cited is quite straightforward. I think you need something like this:
final AWSLogs awsLogs = AWSLogsClientBuilder.defaultClient();
Collection<OutputLogEvent> result = new ArrayList<>();
String nextToken = null;
GetLogEventsResult response;
do {
GetLogEventsRequest request = new GetLogEventsRequest()
.withLogGroupName("myGroup")
.withLogStreamName("myStrean");
if (nextToken != null) request = request.withNextToken(nextToken);
response = awsLogs.getLogEvents(request);
result.addAll(response.getEvents());
// check if token is the same
if (response.getNextForwardToken().equals(nextToken)) break;
// save new token
nextToken = response.getNextForwardToken();
} while (true);
So, you simply need to create request each time with the new token, until it becomes equals to the old one.
I have an ASP application that uploads a PDF file through Request.BinaryRead(Request.TotalBytes). The requests that I make, are made through a java application. The problem is that I have method in Java that iterates through the Header Field Keys of the object HttpURLConnection. When the iteration is made I get in my ASP code an error "cannot call binaryread after using request.form".
Here is my java code:
public String getCookieValue(HttpURLConnection con, String cookieKey) {
String cookieValue = null;
String headerName = null;
for (int i = 1; (headerName = con.getHeaderFieldKey(i)) != null; i++) {
if (headerName.equals("Set-Cookie")) {
String cookie = con.getHeaderField(i);
cookie = cookie.substring(0, cookie.indexOf(";"));
String cookieName = cookie.substring(0, cookie.indexOf("="));
if (cookieName.equals(cookieKey)) {
cookieValue = cookie.substring(cookie.indexOf("=") + 1, cookie.length());
}
}
}
return cookieValue;
}
The exact line of java code that breaks my ASP application is con.getHeaderFieldKey(i). When I upload the file without this Java application, the file is uploaded properly.
What can I do to bypass this issue ?
Thank you
Actually the problem here was that we are using a wrapper for the Session object. When we are trying to retrieve the information regarding the session Id we are using the Request.From method, and this intervenes with the Request.BinaryRead method which generates an error.
When Twilio invokes a callback method to fetch the TwiML <Say> for Voice, I see that Twilio sets "x-twilio-signature" in the HTTP header.
I need to verify that the actual request came from Twilio.
I have a simple war file running on Tomcat and the app is built using Spring.
I did something like the following:
//Get the TwilioUtils object initialized
TwilioUtils twilioUtils = new TwilioUtils("******myAuthToken");
//Get the URL from HttpRequest
String url = httpRequest.getRequestURL().toString();
Map<String, String> allRequestParams = getAllRequestParams(httpRequest);
Map<String, String> headers = getAllRequestHeaders(httpRequest);
//Get the signature generated for the Url and request parameters
//allRequestParams is a map of all request values posted to my service by Twilio
String validSig = twilioUtils.getValidationSignature(url, allRequestParams);
//Get the x-twilio-signature value from the http header map
String xTwilioSignature = headers.get("x-twilio-signatureā€¯);
//This is different from what I get below
logger.info("validSig = " + validSig);
logger.info("xTwilioSignature = " + xTwilioSignature );
//This is always false
logger.info("Signature matched : " + twilioUtils.validateRequest(xTwilioSignature, url,
allRequestParams));
I would like to know what am I doing wrong. Is my approach to validate "x-twilio-signature" incorrect?
If it is incorrect, what's the right way to do it?
I am using the helper library class TwilioUtils provided by Twilio to validate it.
All the time the signature from Twilio is different from what I get from the TwilioUtils object.
Megan from Twilio here.
Are you following the steps suggested in the security documentation?
validateRequest expects three arguments. I believe you're missing the url there.
Consider this example:
public class TwilioUtilsExample {
public static void main(String[] args) {
// Account details
String accountSid = "ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
String authToken = "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY";
//This is the signature we expect
String expected_sig = "SSSSSSSSSSSSSSSSSSSSSSSSSSSS";
//This is the url that twilio requested
String url = "http://UUUUUUUUUUUUUUU";
//These are the post params twilio sent in its request
Map<String,String> params = new HashMap<String,String>();
// Be sure to see the signing notes at twilio.com/docs/security
TwilioUtils util = new TwilioUtils(authToken, accountSid);
boolean result = util.validateRequest(expected_sig, url, params);
if (result) {
System.out.print( "The signature is valid!\n" );
} else {
System.out.print( "The signature was NOT VALID. It might have been spoofed!\n" );
}
}
}
Hope this is helpful!
I have got few things to work e.g. Using -
FB.login(function(response) {
if (response.authResponse) {
console.log('Welcome! Fetching your information.... ');
FB.api('/me', function(response) {
console.log('Good to see you, ' + response.name + '.');
});
} else {
console.log('User cancelled login or did not fully authorize.');
}
});
I am able to get all the details of the user, name, User ID etc.
My Problem is how to take all this information to the server "safely". I don't want this information to be sniffed on its way to server. I use JAVA(Servet/JSP) language, PLEASE HELP ME ON THIS. I wish there was some way like registration plugin where Facebook sends all the information on a redirect_url link.
Regards,
Jagpreet Singh
EDIT: If anybody requires the Java Code -
// it is important to enable url-safe mode for Base64 encoder
Base64 base64 = new Base64(true);
// split request into signature and data
String[] signedRequest = request.getParameter("signed_request").split("\\.", 2);
logger.info("Received signed_request = " + Arrays.toString(signedRequest));
// parse signature
String sig = new String(base64.decode(signedRequest[0].getBytes("UTF-8")));
// parse data and convert to JSON object
JSONObject data = (JSONObject) JSONSerializer.toJSON(new String(base64.decode(signedRequest[1].getBytes("UTF-8"))));
logger.warn("JSON Value = " + data);
// check signature algorithm
if (!"HMAC-SHA256".equals(data.getString("algorithm"))) {
// unknown algorithm is used
logger.error("HMAC-SHA256 Algo? = false, returning ERROR");
return ERROR;
} else {
logger.error("HMAC-SHA256 Algo? = true, Checking if data is signed correctly...");
}
// check if data is signed correctly
if (!hmacSHA256(signedRequest[1], fbSecretKey).equals(sig)) {
// signature is not correct, possibly the data was tampered with
logger.warn("DATA signed correctly? = false, returning ERROR");
return ERROR;
} else {
logger.warn("DATA signed correctly? = true, checking if user has authorized the APP...");
}
// check if user authorized the APP (FACEBOOK User)
if (!data.has("user_id") || !data.has("oauth_token")) {
// this is guest, create authorization url that will be passed
// to javascript
// note that redirect_uri (page the user will be forwarded to
// after authorization) is set to fbCanvasUrl
logger.warn("User has authorized the APP? = false, returning ERROR");
return ERROR;
} else {
logger.warn("User has authorized the APP? = true, Performing User Registration...");
// this is authorized user, get their info from Graph API using
// received access token
// String accessToken = data.getString("oauth_token");
// FacebookClient facebookClient = new
// DefaultFacebookClient(accessToken);
// User user = facebookClient.fetchObject("me", User.class);
}
Facebook sends a signed_request parameter when you authenticate with a client-side method. You can pass this to your server, authenticate it, and then unpack it to get at the information you need. It is encrypted with your app secret, so you can be sure that it is secure.
See the signed_request documentation for more information.
I try to sign in using Google Apps open id with OpenID4Java library.
I discover the user's service using the following code in the consumer class:
try
{
discoveries = consumerManager.discover(identityUrl);
}
catch (DiscoveryException e)
{
throw new OpenIDConsumerException("Error during discovery", e);
}
DiscoveryInformation information = consumerManager.associate(discoveries);
HttpSession session = req.getSession(true);
session.setAttribute(DiscoveryInformation.class.getName(), information);
AuthRequest authReq;
try
{
authReq = consumerManager.authenticate(information, returnToUrl, realm);
// check for OpenID Simple Registration request needed
if (attributesByProvider != null || defaultAttributes != null)
{
//I set the attributes needed for getting the email of the user
}
}
catch (Exception e)
{
throw new OpenIDConsumerException("Error processing ConumerManager authentication", e);
}
return authReq.getDestinationUrl(true);
Next I get the parameters from the http request and in the openid.claimed_id property I receive "http://domain.com/openid?id=...." and if I try to verify the response consumerManager.verify(receivingURL.toString(), openidResp, discovered); an exception is thrown: org.openid4java.discovery.yadis.YadisException: 0x706: GET failed on http://domain.com/openid?id=... : 404:Not Found.
To avoid the exception I tried to modify the parameter list changing the value "http://domain.com/openid?id=...." to "https://www.google.com/a/domain.com/openid?id=...."
// extract the receiving URL from the HTTP request
StringBuffer receivingURL = request.getRequestURL();
String queryString = request.getQueryString();
// extract the parameters from the authentication response
// (which comes in as a HTTP request from the OpenID provider)
ParameterList openidResp = new ParameterList(request.getParameterMap());
Parameter endPoint = openidResp.getParameter("openid.op_endpoint");
if (endPoint != null && endPoint.getValue().startsWith("https://www.google.com/a/"))
{
Parameter parameter = openidResp.getParameter("openid.claimed_id");
if (parameter != null)
{
String value = "https://www.google.com/a/" + parameter.getValue().replaceAll("http://", "");
openidResp.set(new Parameter("openid.claimed_id", value));
queryString = queryString.replaceAll("openid.claimed_id=http%3A%2F%2F", "openid.claimed_id=https%3A%2F%2Fwww.google.com%2Fa%2F");
}
parameter = openidResp.getParameter("openid.identity");
if (parameter != null)
{
String value = "https://www.google.com/a/" + parameter.getValue().replaceAll("http://", "");
openidResp.set(new Parameter("openid.identity", value));
queryString = queryString.replaceAll("openid.claimed_id=http%3A%2F%2F", "openid.claimed_id=https%3A%2F%2Fwww.google.com%2Fa%2F");
}
}
if ((queryString != null) && (queryString.length() > 0))
{
receivingURL.append("?").append(queryString);
}
// retrieve the previously stored discovery information
DiscoveryInformation discovered = (DiscoveryInformation) request.getSession().getAttribute(DiscoveryInformation.class.getName());
// verify the response
VerificationResult verification;
Map userDetails = new HashMap();
try
{
verification = consumerManager.verify(receivingURL.toString(), openidResp, discovered);
// check for OpenID Simple Registration request needed
if (attributesByProvider != null || defaultAttributes != null)
{
//Here I get the value of requested attributes
}
}
catch (Exception e)
{
throw new OpenIDConsumerException("Error verifying openid response", e);
}
// examine the verification result and extract the verified identifier
Identifier verified = null;
if (verification != null)
{
verified = verification.getVerifiedId();
}
OpenIDAuthenticationToken returnToken;
List attributes = null;
if (verified != null)
returnToken = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.SUCCESS, verified.getIdentifier(), "some message", attributes);
else
{
Identifier id = discovered.getClaimedIdentifier();
return new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.FAILURE, id == null ? "Unknown" : id.getIdentifier(), "Verification status message: [" + verification.getStatusMsg() + "]", attributes);
}
Now the method consumerManager.verify is not throwing anymore exception, but its status is changed to failed. In log the following errors appear
09:46:45,424 ERROR ConsumerManager,http-80-1:1759 - No service element found to match the ClaimedID / OP-endpoint in the assertion.
09:46:45,428 ERROR ConsumerManager,http-80-1:1183 - Discovered information verification failed.
I saw on a forum a similar problem, but the solution was to change consumerManager.verify to consumerManager.verifyNonce. I'm not sure if using this method will not create a security issue. Do you have any idea what should I change to make my open id consumer to work with Google Apps openid?
Google Apps uses a slightly different discovery process than what is supported in the base version of OpenID4Java. There's an add-on library at http://code.google.com/p/step2/ that you might fight useful (and a higher level wrapper at http://code.google.com/p/openid-filter/.)
I'm not aware of anyone that has done Spring Security integration with the modified Step2 classes, but it shouldn't be too hard to modify the code to set up Step2 appropriately. It's built on OpenID4Java and the code to write a relying party is mostly the same.