Problems with JavaMail, GMail and OAUTH2 (not Android) - oauth-2.0

I'm having a problem connecting to GMail with JavaMail in a non-android environment. I'm being given an OAuth2 access token, which I believe to be correct. But when I try to use this access token to connect, I get an exception:
javax.mail.AuthenticationFailedException: [AUTHENTICATIONFAILED] Invalid credentials (Failure)
It looks, to me, like the Java SASL code is expecting two return values (a username and a password callback?), but is only getting one.
I've boiled the problem down to this code:
import java.io.IOException;
import java.util.Properties;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Store;
public class TestImap {
private String userId;
private String accessToken;
public TestImap(String[] args) {
userId = args[0];
accessToken = args[1];
}
public void connectImap()
throws MessagingException
{
System.out.println("Connecting to gmail with IMAP and OAUTH2.");
Properties props = new Properties();
props.put("mail.imaps.ssl.enable", "true");
props.put("mail.imaps.sasl.enable", "true");
props.put("mail.imaps.sasl.mechanisms", "XOAUTH2");
props.put("mail.imaps.auth.login.disable", "true");
props.put("mail.imaps.auth.plain.disable", "true");
props.put("mail.debug.auth", "true");
/*
props.put("mail.imaps.sasl.mechanisms.oauth2.oauthToken",
accessToken);
*/
System.out.println("Creating session...");
Session session = Session.getInstance(props);
session.setDebug(true);
System.out.println("Creating store...");
Store store = session.getStore("imaps");
System.out.println("Connecting store...");
store.connect("imap.gmail.com", 993, userId, accessToken);
System.out.println("Store connected. If we get here, things work.");
}
public static void main(String[] args) {
TestImap test = new TestImap(args);
try {
test.connectImap();
} catch (Throwable e) {
System.out.println("Died throwing an exception: ");
e.printStackTrace();
}
}
}
That, when run, gives the following output:
Connecting to gmail with IMAP and OAUTH2.
Creating session...
DEBUG: setDebug: JavaMail version 1.5.3
Creating store...
DEBUG: getProvider() returning javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle]
DEBUG IMAPS: mail.imap.fetchsize: 16384
DEBUG IMAPS: mail.imap.ignorebodystructuresize: false
DEBUG IMAPS: mail.imap.statuscachetimeout: 1000
DEBUG IMAPS: mail.imap.appendbuffersize: -1
DEBUG IMAPS: mail.imap.minidletime: 10
DEBUG IMAPS: disable AUTH=LOGIN
DEBUG IMAPS: disable AUTH=PLAIN
DEBUG IMAPS: enable SASL
DEBUG IMAPS: SASL mechanisms allowed: XOAUTH2
DEBUG IMAPS: closeFoldersOnStoreFailure
Connecting store...
DEBUG IMAPS: trying to connect to host "imap.gmail.com", port 993, isSSL true
* OK Gimap ready for requests from 162.243.86.176 d92mb281521696qgf
A0 CAPABILITY
* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 XYZZY SASL-IR AUTH=XOAUTH AUTH=XOAUTH2 AUTH=PLAIN AUTH=PLAIN-CLIENTTOKEN
A0 OK Thats all she wrote! d92mb281521696qgf
DEBUG IMAPS: AUTH: XOAUTH
DEBUG IMAPS: AUTH: XOAUTH2
DEBUG IMAPS: AUTH: PLAIN
DEBUG IMAPS: AUTH: PLAIN-CLIENTTOKEN
DEBUG IMAPS: protocolConnect login, host=imap.gmail.com, user=bhurt42#gmail.com, password=<non-null>
DEBUG IMAPS: SASL Mechanisms:
DEBUG IMAPS: XOAUTH2
DEBUG IMAPS:
DEBUG IMAPS: SASL client XOAUTH2
DEBUG IMAPS: SASL callback length: 2
DEBUG IMAPS: SASL callback 0: javax.security.auth.callback.NameCallback#268d5581
DEBUG IMAPS: SASL callback 1: javax.security.auth.callback.PasswordCallback#8e89bed
A1 AUTHENTICATE XOAUTH2 dXNlcj1iaHVydDQyQGdtYWlsLmNvbQFhdXRoPUJlYXJlciB5YTI5LldBRjY1ZGZZT3YyWEdTdkozOWdTUEswN2ZHeWhCdFNjeWp0WFlGTHliN2NobHAyemlFa0MtNFo2UWdmMG9UQWR4b2NiZXpHX2ZPdW91dwEB
+ eyJzdGF0dXMiOiI0MDAiLCJzY2hlbWVzIjoiQmVhcmVyIiwic2NvcGUiOiJodHRwczovL21haWwuZ29vZ2xlLmNvbS8ifQ==
DEBUG IMAPS: SASL no response
A1 NO [AUTHENTICATIONFAILED] Invalid credentials (Failure)
Died throwing an exception:
javax.mail.AuthenticationFailedException: [AUTHENTICATIONFAILED] Invalid credentials (Failure)
at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:722)
at javax.mail.Service.connect(Service.java:364)
at TestImap.connectImap(TestImap.java:38)
at TestImap.main(TestImap.java:45)
This is with JavaMail 1.5.3. I've googled this question, and most of the answers I've found so far are sufficiently old that I'm pretty sure they predate JavaMail supporting google natively.
Any help would be greatly appreciated. Thanks.

Related

Invalid Request 409 when trying to subscribe to Microsoft Graph for Presence

Executing a subscription to presence request for users with the SDK targeting the MS Graph API is resulting in an error:
409Graph service exception Error code: InvalidRequest
Throwable detail: com.microsoft.graph.http.GraphServiceException: Error code: InvalidRequest
Error message: The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
POST https://graph.microsoft.com/v1.0/subscriptions
SdkVersion : graph-java/v5.16.0
SdkVersion : graph-java/v5.16.0
[...]
400 : Bad Request
[...]
My code is:
final Subscription subscriptionRequest = new Subscription();
subscriptionRequest.changeType = ChangeType.UPDATED.toString();
subscriptionRequest.notificationUrl = notificationsHost;
subscriptionRequest.resource = "/communications/presences?$filter=id in ("+userIdsSb.toString()+")";
subscriptionRequest.clientState = subscribeToPresenceRequest.getClientState();
}el
subscriptionRequest.clientState = UUID.randomUUID().toString();
subscriptionRequest.expirationDateTime = OffsetDateTime.now().plusHours(1);
Subscription subscription = null;
try {
subscription = graphClient.subscriptions().buildRequest().post(subscriptionRequest);
response.setSubscribed(false);
failedIds.addAll(this.getFailedIds(e));
log.error("Error while trying to execute subscribeToPresence. ", e);
if(failedIds!=null && !failedIds.isEmpty()) {
log.error("The ids {} failed during the subscription request ",failedIds);
response.setFailedIds(failedIds);
}
}catch(Exception e) {
log.error("General Error while trying to execute subscribeToPresence. ", e);
retur
}
My subscription request includes the following values:
applicationId: null
changeType: UPDATED
clientState: 7fc6bf6b-6cc2-438d-a293-aa47539ad02a
creatorId: null
id: null
latestSupportedTlsVersion: null
lifecycleNotificationUrl: null
notificationQueryOptions: null
notificationUrl: https://myhost:port/graph/listen
notificationUrlAppId: null
oDataType: null
resource: /communications/presences?$filter=id in ('932b90ca-e5a4-42c7-a985-f4ddfc6d6715','6be2455d-63ac-4423-aa3e-7188fdbd5e73','41b3d168-5c28-4596-ba3b-d5c70a3c3967','8830a8bc-f882-4c13-b33a-7031423b5a24','ab548af7-d5a9-4388-9800-7668a20bb2b9')
expirationDateTime: 2023-02-02T16:41:11.737+02:00
includeResourceData: false
I saw this article regarding the beta version of the sdk https://learn.microsoft.com/en-us/graph/api/resources/subscription?view=graph-rest-1.0.
It indicates "Subscriptions to resources marked with an asterisk (*) are available on the /beta endpoint only." and presence is one of those resources. Is this related to my error?
I tried to use this version instead, but I still have the same Invalid request error.
I am using delegated permission to call the /subscription/presence endpoint of the Microsoft Graph API.
I was able to fetch previous subscriptions by calling /subscription endpoint and was also able to find users through /users/filter endpoint with application permission.
Is there something wrong in the format of my subscription request? This all worked fine a few months ago and I haven't changed anything.
Is this related to SSL/TLS secure communication? But then again, why would my other requests get responses?

Tapkey token exchange is successful, but getting a 400 Bad Request when trying to login

I am successfully using the Tapkey token exchange endpoint to exchange a Firebase token for a Tapkey one, but am then having an error calling login.
I am requested the following Scope's when exchanging the token:
register:mobiles read:user read:ip:users handle:keys
My swift code is below (basically lifted straight from the documentation):
let authToken = ExchangeFirebaseTokenForTapkeyToken(firebaseToken);
if authToken == nil {
return
}
// For testing purposes, normally this would be static and only built once
let serviceFactory = TKMServiceFactoryBuilder()
.setTokenRefreshHandler(TapkeyTokenRefreshHandler())
.build()
let userManager = serviceFactory.userManager
let result = userManager.logInAsync(accessToken: authToken!, cancellationToken: TKMCancellationTokens.None)
result.continueOnUi { (userId) -> Void in
print(userId as Any)
}
.catchOnUi { (error) -> Void in
print(error)
}
.conclude()
The logs are below, as you can see I get a Failed to authenticateAsync error, and a HTTP 400 response.
2021-06-14 14:25:48.805135+0100 App[11940:234234] LogonManager: start authentication
Jun 14 14:25:48 [11940] : LogonManager: start authentication
2021-06-14 14:25:48.805917+0100 App[11940:234234] NetTpkyMcRestLoggingAsyncHttpRequestExecutor: Request POST 'https://my.tapkey.com/api/v1/Auth/Auth/UserInfo?t=tk' started.
Jun 14 14:25:48 [11940] : NetTpkyMcRestLoggingAsyncHttpRequestExecutor: Request POST 'https://my.tapkey.com/api/v1/Auth/Auth/UserInfo?t=tk' started.
2021-06-14 14:25:49.464429+0100 App[11940:234234] NetTpkyMcRestLoggingAsyncHttpRequestExecutor: Request POST 'https://my.tapkey.com/api/v1/Auth/Auth/UserInfo?t=tk' completed with code 400 after 659ms.
Jun 14 14:25:49 [11940] : NetTpkyMcRestLoggingAsyncHttpRequestExecutor: Request POST 'https://my.tapkey.com/api/v1/Auth/Auth/UserInfo?t=tk' completed with code 400 after 659ms.
2021-06-14 14:25:49.476961+0100 App[11940:234234] AuthenticationManagerImpl: Failed to authenticateAsync
If I provide any value other than the access key returned from the Token Exchange endpoint, I get a 401 Unauthorised (which is to be expected).
I have tried adding this user to the portal, but I still have the same issue.
Is there anything else I need to do, or any extra configuration I need to add to my iOS app? I have matched my configuration with the sample app (as far as I can tell) to no avail.
Thanks
Users of external identity providers have to be registered before the can login.
You can find the details here:
https://developers.tapkey.io/api/authentication/identity_providers/#working-with-users
When it is necessary for your use case, that these users are automatically created when they login, please send a request to tapkey support and they will enable this feature for you.

AWS Cognito Tokens Invalid after Sign in with Apple

After a "successful" federated Sign in with Apple I get the message on the console that the tokens are not valid. How can I refresh them?
AWSMobileClient.default().federatedSignIn(providerName: IdentityProvider.apple.rawValue, token: token) { (userState, error) in
if let error = error {
print("Federated Sign In failed: \(error.localizedDescription)")
}else{
print("federatedSignIn successful: \(userState)")
}
}
On the console I get this even listener. Right after login , it gets signed out, so the user can't make any API calls
AWSMobileClient Event listener - signedIn
AWSMobileClient Event listener - signedOutFederatedTokensInvalid

Trouble receiving notifications from iTunes Connect about IAP status change events

I've set up a URL on my server to receive auto-renewable IAP status change notifications per this article:
https://help.apple.com/itunes-connect/developer/#/dev0067a330b
And of course I've provided my URL to iTunes Connect via my app's main settings page.
However, I'm receiving neither update notifications nor any kind of message indicating that there's a problem.
Help troubleshooting? I don't even know where to start.
Thanks!
Have you checked secure network connection with your server? I mean that you have to check ATS on your server. I'm using nginx such as proxy server. First of all, you have to check your nginx system pair past with ATS to connect with apple server.
This method to check ATS pass on nginx server
nscurl --ats-diagnostics <your status receive url>
See more on apple documentation Using the nscurl Tool to Diagnose ATS Connection Issues
If your server passed. You are ready to receive response from apple.
My subscription status URL setup simple such as a simple http service created on nodejs ( express framwork )
const express = require('express')
const app = express()
const bodyParser = require('body-parser');
const path = require('path');
process.on('uncaughtException', function (err) {
console.log(err.stack);
});
process.on('exit', function (code) {
console.log('About to exit with code: ' + code);
});
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: false }))
// parse application/json
app.use(bodyParser.json())
app.post('/', function (req, res) {
console.log(req.body); < response from apple is here >
res.send({ ok: 1 });
})
const port = 12092;
app.listen(port, function () {
console.log('Subscription status url ping on port ' + port);
});
By the way, you should update your question. you can reference from a other relation question on your question. This's more helpful!.

Issue with unregistering and registering to a different server

I've encountered an issue with registration and unregistering in my app. For Development purposes we have 3 instances of SUP. The following scenario causes ErrorCode 568;
Create database & register with UAT Server (Success)
Perform an Initial Sync with server (Success)
Unregister with UAT Server & delete database (Success)
Create database & register with DEV Server (Success)
Perform an Initial Sync with server (Success)
Unregister with DEV Server & delete database (Success)
Create database & register with UAT Server (Fail)
Error Output:
[ERROR] [SUPApplication.m:1171] error # registerApplication MessagingClientException {
ErrorCode = 568;
ErrorMessage = "";
}
=================================================
onRegistrationStatusChanged: status = 201, code = 568, message = SUPApplicationError_UNKNOWN
=================================================
[Line 420] Exception: SUPPersistenceException: Sync failed: -1497 (ERROR) %1:3 %2:3004;Parameter 1:3;Parameter 2:3004
Attempt 1: I thought calling [[SUPApplication getInstance] clearApplicationState] would help but now with the following steps I constantly receive ErrorCode 516;
Create database & register with UAT Server (Success)
Perform an Initial Sync with server (Success)
Unregister with UAT Server & delete database (Success)
Create database & register with DEV Server (Fail)
I tried it in reverse and got the same error (Started at DEV and tried to register with DEV)
Error Output:
[SUPApplication.m:1171] error # registerApplication MessagingClientException {
ErrorCode = 516;
ErrorMessage = "";
}
=================================================
onRegistrationStatusChanged: status = 201, code = 516, message = SUPApplicationError_REGISTRATION_Resetting Communications
=================================================
[Line 420] Exception: SUPPersistenceException: Sync failed: -1497 (ERROR) %1:3 %2:3004;Parameter 1:3;Parameter 2:3004
What I know
Performing the first two steps and synchronising I am always getting data
Aside from the connection settings in the MBO on the SCC, both the
application settings are identical
I am setting the applicationIdentifier each time I register
I am wondering if anyone else has encountered this issue before and what the solution was?

Resources