I am trying to authenticate a java app to AWS services using a developer-authenticated Cognito identity. This is very straightforward in the AWS mobile SDKs (documentation), but I can't seem to find the equivalent classes in the Java SDK.
The main issue I am having is that the Java SDK classes (such as WebIdentityFederationSessionCredentialsProvider) require the client code to know the arn of the role being assumed. With the mobile SDK, it uses the role configured for the federated identity. That's what I'd prefer to do, but it seems the Java SDK doesn't have the supporting classes for that.
The last comment from Jeff led me to the answer. Thanks Jeff!
String cognitoIdentityId = "your user's identity id";
String openIdToken = "open id token for the user created on backend";
Map<String,String> logins = new HashMap<>();
logins.put("cognito-identity.amazonaws.com", openIdToken);
GetCredentialsForIdentityRequest getCredentialsRequest =
new GetCredentialsForIdentityRequest()
.withIdentityId(cognitoIdentityId)
.withLogins(logins);
AmazonCognitoIdentityClient cognitoIdentityClient = new AmazonCognitoIdentityClient();
GetCredentialsForIdentityResult getCredentialsResult = cognitoIdentityClient.getCredentialsForIdentity(getCredentialsRequest);
Credentials credentials = getCredentialsResult.getCredentials();
AWSSessionCredentials sessionCredentials = new BasicSessionCredentials(
credentials.getAccessKeyId(),
credentials.getSecretKey(),
credentials.getSessionToken()
);
AmazonS3Client s3Client = new AmazonS3Client(sessionCredentials);
...
If that's the route you want to go, you can find this role in the IAM console, named Cognito_(Auth|Unauth)_DefaultRole. These are what Cognito generated and linked to your pool, and you can get the ARN from there.
This blog post may be of some assistance. All of the APIs the SDK uses to communicate with Cognito to get credentials are exposed in the Java SDK, you just need to use your own back end to get the token itself. Once you have it, you can set the logins the same way you normally would with another provider and it'll all work.
Related
String userPoolId="testPoolID";
String username= "testuser";
String amazonAWSAccessKey="test access key";
String amazonAWSSecretKey="test secret key";
AdminDeleteUserRequest req = new AdminDeleteUserRequest();
req.setUsername(username);
req.setUserPoolId(userPoolId);
AWSCredentials credentials = new BasicAWSCredentials(amazonAWSAccessKey, amazonAWSSecretKey);
AWSCredentialsProvider credentialsProvider = new AWSStaticCredentialsProvider(credentials);
credentialsProvider.getCredentials();
req.setRequestCredentialsProvider(credentialsProvider);
AWSCognitoIdentityProvider provider = new AWSCognitoIdentityProviderClient();
provider.adminDeleteUser(req);
This is the code snippet for deleting a user from cognito User pool. How we can delete a user from cogito without providing credentials using java ?
One way to do this would be to put this code in a lambda & expose it via API Gateway. Create another userpool for admins (its free!) & enable cognito userpool authorizers for your API. Now in your code, show a login screen (use Cognito's built-in UI) ,get the ID tokens and use this ID token while calling your API. This way your code will dynamically get tokens & so no hard-coded credentials.
Another way would be to use Cognito Federated Identities but in this case no lambda + API Gateway is needed. Again, create a userpool for Admins & add this as an Auth Provider in a Cognito Identity Pool. Now, login to the Admin userpool, get an Id token, use this token in the login map for the IdentityPool & get temporary credentials using GetCredentialsForIdentity. Just make sure that the Auth role for the Cognito Identity Pool has appropriate permissions to perform userpool actions.
Sorry its late, might be helpful for others who stumble on this.
If your code is in a lambda you can use the following code
AWSCognitoIdentityProviderClientBuilder.standard()
.withCredentials(DefaultAWSCredentialsProviderChain.getInstance())
.withRegion(region).build();
Note: Check if your lambda execution role is having access to cognito
My Guidelines
If followed this Google documentation about verifying Google-Account-Tokens on the server side, but I am kinda confused.
My Problem
GoogleIdTokenVerifier googleIdTokenVerifier = new GoogleIdTokenVerifier.Builder(new NetHttpTransport(), new JacksonFactory())
.setAudience(Collections.singletonList(CLIENT_ID))
.build();
In this piece of code I figured out that the transport and jsonFactory arguments can be filled as new NetHttpTransport() and new JacksonFactory() here. It also describes how to get AudienceString, but I couldn't figure out what it is for. I couldn't test it, but my question is if I can use it without .setAudience() or if I need it and what it is for.
In .setAudience() you have to pass all client ID's. You can get the ID for your client from the Credentials Page. It's explained here.
Thanks to #StevenSoneff.
If you didn't get the basic concept
For every client you want your server to accept, you need to create a project in the `Developer Console`. Clients are differentiated by their `SHA-1` fingerprint. You can for example have a debug project (will take your debug fingerprint) and a release one. To make both work, you have to add both `ID`'s to your server's `GoogleIdTokenVerifier`'s `.setAudience()`.
In my case, If you're using Firebase to get the id token on Android or iOS. You should follow these instructions to verify it on your backend server.
Verify ID tokens using a third-party JWT library
For me, I'm using Google OAuth Client as the third-party library so it's easy to use.
But it's a little bit different from this document.
Verify the Google ID token on your server side
The CLIENT_ID is your firebase project ID.
The Issuer has to be set as https://securetoken.google.com/<projectId>.
You need to use GooglePublicKeysManager and call setPublicCertsEncodedUrl to set it as https://www.googleapis.com/robot/v1/metadata/x509/securetoken#system.gserviceaccount.com
GooglePublicKeysManager manager = new GooglePublicKeysManager.Builder(HTTP_TRANSPORT, JSON_FACTORY)
.setPublicCertsEncodedUrl(PUBLIC_KEY_URL)
.build();
GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(manager)
.setAudience(Collections.singletonList(FIREBASE_PROJECT_ID))
.setIssuer(ISSUER)
.build();
If you have multiple issuers, then you have to create GoogleIdTokenVerifier for each one.
In order to get access to exchange servers we use:
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010_SP2);
ExchangeCredentials credentials = new WebCredentials("emailAddress", "password");
service.setCredentials(credentials);
Is there an option to retrieve user's items with a master/admin password?
For example;
credentials = anyMethod("adminUser", "adminPassword", "emailAddress")
or
List items = anyMethodRetriveItems("emailAddress");
etc.
Well I found the solution asked the same question on GitHub Page. Here is the link of question .
André Behrens (aka serious6) recommend to use impersonation or delegated access.
impersonation worked fine for me. But we had to give permission to a user.
Setting up a user for impersonation check Exchange Server 2010 or check Exchange Server 2013 due to your exchange version.
Enjoy it
If a user has already authorized our app for OAuth 1 (so we have a valid token/secret pair for this user), is it possible to get a valid OAuth 2.0 access token without the user having to explicitly re-authorize our app again? I know that some APIs support this (e.g. Soundcloud and I think also Google), but I haven't found anything related to OAuth token migration in the Dropbox API documentation.
Context: We have an application in Java that accesses the Dropbox API with OAuth 1.0a using the Scribe OAuth library and want to migrate to the official Dropbox Java API that only supports OAuth 2 (and we don't want to have all our users having to re-authorize us).
Just for people stumbling upon this, the API for this is now there: https://www.dropbox.com/developers/core/docs#oa2-from-oa1
From their Java SDK, I used their Upgrader class like so
DbxOAuth1Upgrader upgrader;
DbxOAuth1AccessToken oAuth1AccessToken;
try {
DbxRequestConfig requestConfig = new DbxRequestConfig("Your App", Locale.getDefault().toString());
DbxAppInfo appInfo = new DbxAppInfo(DROPBOX_APP_KEY, DROPBOX_APP_SECRET);
upgrader = new DbxOAuth1Upgrader(requestConfig, appInfo);
oAuth1AccessToken = new DbxOAuth1AccessToken(oauth1AccessKey, oauth1AccessSecret);
String newToken = upgrader.createOAuth2AccessToken(oAuth1AccessToken);
upgrader.disableOAuth1AccessToken(oAuth1AccessToken);
return newToken;
} catch (Exception e) {
//deal with it
}
It's snipped for relevance but if you're doing this in Android, make sure you do it inside an AsyncTask otherwise it throws an exception for performing work on the main thread.
See also the answer on the Dropbox forum: https://forums.dropbox.com/topic.php?id=107766. For now, there's no automated way today to do this migration.
Does anyone know how to use 2-legged OAuth with google-api-java-client?
I'm trying to access the Google Apps Provisioning API to get the list of users for a particular domain.
The following does not work
HttpTransport transport = GoogleTransport.create();
GoogleHeaders headers = (GoogleHeaders) transport.defaultHeaders;
headers.setApplicationName(APPLICATION_NAME);
headers.gdataVersion = GDATA_VERSION;
OAuthHmacSigner signer = new OAuthHmacSigner();
signer.clientSharedSecret = CONSUMER_SECRET;
OAuthParameters oauthParameters = new OAuthParameters();
oauthParameters.version = OAUTH_VERSION;
oauthParameters.consumerKey = CONSUMER_KEY;
oauthParameters.signer = signer;
oauthParameters.signRequestsUsingAuthorizationHeader(transport);
I get the "com.google.api.client.http.HttpResponseException: 401 Unknown authorization header".
The header looks something like this
OAuth oauth_consumer_key="...", oauth_nonce="...", oauth_signature="...", oauth_signature_method="HMAC-SHA1", oauth_timestamp="...", oauth_version="1.0"
I also tried following without success
GoogleOAuthDomainWideDelegation delegation = new GoogleOAuthDomainWideDelegation();
delegation.requestorId = REQUESTOR_ID;
delegation.signRequests(transport, oauthParameters);
Any ideas?
Thanks in advance.
It seems that there was nothing wrong with the code. It actually works.
The problem was with the our Google Apps setup.
When you visit the "Manage OAuth key and secret for this domain" page (https://www.google.com/a/cpanel/YOUR-DOMAIN/SetupOAuth),
and enable "Two-legged OAuth access control" and select
"Allow access to all APIs", it doesn't actually allow access to all APIs.
If you visit the "Manage API client access" page after that
(https://www.google.com/a/cpanel/YOUR-DOMAIN/ManageOauthClients),
you'll see that there is an entry like:
YOR-DOMAIN/CONSUMER-KEY "This client has access to all APIs"
It seems that this doesn't include Provisioning API.
Only after we explicitly added the Provisioning API, the code started to work.
So to enable Provisioning API, you should also have something like the following entry in your list:
YOR-DOMAIN/CONSUMER-KEY Groups Provisioning (Read only) https://apps-apis.google.com/a/feeds/group/#readonly
User Provisioning (Read only) https://apps-apis.google.com/a/feeds/user/#readonly
Somone else had the same problem:
http://www.gnegg.ch/2010/06/google-apps-provisioning-two-legged-oauth/
Sasa
Presumably you are trying to get an unauthorised request token here? I Haven't used the Google implementation, but the OAuth 1.0a spec says you need a callback URL, which you don't have. This might be a red herring as the spec says a missing param should return HTTP code 400 not 401.
See http://oauth.net/core/1.0a/#auth_step1