Google OAuth 2.0 Authentication throwing SocketTimeoutException : Read timeout - oauth-2.0

I am trying to authenticate with Google using OAuth 2.0 for GAMv2 Apps.
GoogleCredential.Builder credentialBuilder = new GoogleCredential.Builder();
credentialBuilder.setTransport(httpTransport).setJsonFactory(jsonFactory);
credentialBuilder.setServiceAccountId(serviceAccountId);
credentialBuilder.setServiceAccountPrivateKeyFromP12File(new File(p12FileURL.toURI()));
credentialBuilder.setServiceAccountScopes(scopes);
credentialBuilder.setServiceAccountUser(userEmail);
credential = credentialBuilder.build();
credential.refreshToken();
Oauth2 userInfoService = new Oauth2.Builder(new NetHttpTransport(), new JacksonFactory(), credential).setApplicationName(applicationName).build();
Userinfoplus userInfo = null;
try
{
userInfo = userInfoService.userinfo().get().execute();
}
catch (IOException e)
{
logger.error("Exception_Thrown while getting User Info:", e);
}
I am using the above code for getting the userInfo and facing the following exception :
java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at com.sun.net.ssl.internal.ssl.InputRecord.readFully(InputRecord.java:293)
at com.sun.net.ssl.internal.ssl.InputRecord.read(InputRecord.java:331)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:798)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:755)
at com.sun.net.ssl.internal.ssl.AppInputStream.read(AppInputStream.java:75)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:258)
at java.io.BufferedInputStream.read(BufferedInputStream.java:317)
at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:687)
at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:632)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1195)
at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:379)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:318)
at com.google.api.client.http.javanet.NetHttpResponse.<init>(NetHttpResponse.java:36)
at com.google.api.client.http.javanet.NetHttpRequest.execute(NetHttpRequest.java:94)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:965)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:410)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:343)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:460)
Until last few days, it was fine. Only in a couple of days now we are facing this issue.
Can anyone help with this issue ?
Thanks in advance.

you can get instance of HttpRequestInitializer from Oauth2.Builder and pass it as input parameter
private static HttpRequestInitializer setHttpTimeout(final HttpRequestInitializer requestInitializer) {
return new HttpRequestInitializer() {
#Override
public void initialize(HttpRequest httpRequest) throws IOException {
requestInitializer.initialize(httpRequest);
httpRequest.setConnectTimeout(3 * 60000); // 3 minutes connect timeout
httpRequest.setReadTimeout(3 * 60000); // 3 minutes read timeout
}
};
}

Related

How to Implement Flutter Web SSL Certificate (SSL Pinning)

I am building a flutter web app and I need to use SSL to talk to the server using a .pem certificate.
I am using HttpClient and IOClient to get it to work and the code for this looks as following:
fetchData()async{
HttpClient _client = HttpClient(context: await globalContext);
_client.badCertificateCallback =
(X509Certificate cert, String host, int port) => false;
IOClient _ioClient = new IOClient(_client);
var response = await _ioClient.get(Uri.parse('https://appapi2.test.bankid.com/rp/v5.1'));
print(response.body);
}
Future<SecurityContext> get globalContext async {
final sslCert1 = await
rootBundle.load('assets/certificates/bankid/cert.pem');
SecurityContext sc = new SecurityContext(withTrustedRoots: false);
sc.setTrustedCertificatesBytes(sslCert1.buffer.asInt8List());
return sc;
}
I get the following error when trying to run fetchData:
Unsupported operation: SecurityContext constructor
I have also tried using the flutter plugin DIO that looks like this:
void bid() async {
final dio = Dio();
ByteData bytes = await rootBundle
.load('assets/certificates/bankid/FPTestcert4_20220818.pem');
(dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
(client) {
SecurityContext sc = SecurityContext();
sc.setTrustedCertificatesBytes(bytes.buffer.asUint8List());
HttpClient httpClient = HttpClient(context: sc);
return httpClient;
};
try {
var response = await dio.get('https://appapi2.test.bankid.com/rp/v5.1');
print(response.data);
} catch (error) {
if (error is DioError) {
print(error.toString());
} else {
print('Unexpected Error');
}
}
}
When running this I get the following error:
Error: Expected a value of type 'DefaultHttpClientAdapter', but got one of type
'BrowserHttpClientAdapter'
I understand that I get the error above because of the casting that the httpClientAdapter is used as a DefaultHttpClientAdapter but since the app is running in the browser its using BrowserHttpClientAdapter, but how do I solve this?
Is it possible to make this work?

"invalid_client" in Spring Security when using private_key_jwt instead of client_secret_basic

I have tried to switch from client_secret_basic to private_key_jwt, but I'm getting the following error when I'm sent back from the auth provider:
[invalid_client] Client authentication failed. No client authentication included
It's not a Spring Boot app, but this is what I have done so far:
private ClientRegistration idPortenClientRegistration() {
return ClientRegistrations
.fromIssuerLocation("the endpoint")
.clientId("the client id")
.registrationId("idporten")
.authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
.redirectUri("the redirect url")
.scope(Arrays.asList("the scopes"))
.userNameAttributeName(IdTokenClaimNames.SUB)
.clientName("idporten")
.clientAuthenticationMethod(ClientAuthenticationMethod.PRIVATE_KEY_JWT);
.build();
}
My SecurityConfig.class:
http.oauth2Client(oauth2 -> oauth2
.authorizationCodeGrant(codeGrant -> codeGrant
.accessTokenResponseClient(accessTokenResponseClient())));
[…]
private DefaultAuthorizationCodeTokenResponseClient accessTokenResponseClient() {
OAuth2AuthorizationCodeGrantRequestEntityConverter requestEntityConverter = new OAuth2AuthorizationCodeGrantRequestEntityConverter();
requestEntityConverter.addParametersConverter(
new NimbusJwtClientAuthenticationParametersConverter<>(jwkResolver));
DefaultAuthorizationCodeTokenResponseClient tokenResponseClient = new DefaultAuthorizationCodeTokenResponseClient();
tokenResponseClient.setRequestEntityConverter(requestEntityConverter);
return tokenResponseClient;
}
private Function<ClientRegistration, JWK> jwkResolver = (clientRegistration) -> {
if (clientRegistration.getClientAuthenticationMethod().equals(ClientAuthenticationMethod.PRIVATE_KEY_JWT)) {
JKSKeyManager keyManager = getApplicationContext().getBean("keyManager", JKSKeyManager.class);
try {
RSAPublicKey publicKey = (RSAPublicKey) keyManager.getPublicKey("idporten1");
KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry) keyManager.getKeyStore()
.getEntry("idporten1", new KeyStore.PasswordProtection(keyEntryPassword1.toCharArray()));
RSAPrivateKey privateKey = (RSAPrivateKey) pkEntry.getPrivateKey();
return new RSAKey.Builder(publicKey).privateKey(privateKey).keyID(UUID.randomUUID().toString()).build();
} catch (NoSuchAlgorithmException | UnrecoverableEntryException | KeyStoreException e) {
logger.error("Failed to configure jwkResolver: " + e.getMessage(), e);
}
}
return null;
};
As mentioned, I'm successfully redirected to the auth provider, but getting the error described above when I'm sent back to the application. I have also tried to log accessTokenResponseClient() and jwkResolver. The former method gets called just before the error occurs, but nothing gets logged from the latter.
Some documentation from the provider:
https://docs.digdir.no/oidc_protocol_token.html
https://oidc-ver2.difi.no/idporten-oidc-provider/.well-known/openid-configuration

How to handle incorrect credentials with google oauth2 Installed Application code flow

I'm implementing the authorization code flow for Installed Application.
Code is similar to snippet below:
public static void main(String[] args) {
try {
httpTransport = GoogleNetHttpTransport.newTrustedTransport();
dataStoreFactory = new FileDataStoreFactory(DATA_STORE_DIR);
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(httpTransport,
JSON_FACTORY,
IA_CLIENT,
IA_SECRET,
Collections.singleton(DriveScopes.DRIVE)).setDataStoreFactory(dataStoreFactory)
.build();
Credential credential = new AuthorizationCodeInstalledApp(flow, new LocalServerReceiver()).authorize("user");
drive = new Drive.Builder(httpTransport, JSON_FACTORY, credential).setApplicationName(APPLICATION_NAME).build();
System.out.println(drive.about());
return;
} catch (IOException e) {
System.err.println(e.getMessage());
} catch (Throwable t) {
t.printStackTrace();
}
System.exit(1);
}
Everything is working fine except in the case when I provide an invalid client_id. (I've the same issue if I use a json file and alter its content).
I get this get of error message from Google server:
401. That’s an error.
Error: invalid_client
The OAuth client was not found.
Request Details
client_id=573900000-hsoobsdsstem84tg8br4pmdsds.apps.googleusercontent.com
redirect_uri=http://localhost:40441/Callback
response_type=code
scope=https://www.googleapis.com/auth/drive
... and the callback server never receives any feedback. So, the application
is still running endlessly.
I've looked at the LocalServerReceiver class but could find any way to provide a
timeout or any potential solution.
What's the cleanest way to handle this case ?

Volley android "javax.net.ssl.SSLHandshakeException: Handshake failed"

Hi I'm rebuilding a API call using volley library
this is my test code to send XML data and receive xml response (I just need to successfully receive response in string format)
String url ="https://prdesb1.singpost.com/ma/FilterOverseasPostalInfo";
final String payload = "<OverseasPostalInfoDetailsRequest xmlns=\"http://singpost.com/paw/ns\"><Country>AFAFG</Country><Weight>100</Weight><DeliveryServiceName></DeliveryServiceName><ItemType></ItemType><PriceRange>999</PriceRange><DeliveryTimeRange>999</DeliveryTimeRange></OverseasPostalInfoDetailsRequest>\n";
RequestQueue mRequestQueue;
// Instantiate the cache
Cache cache = new DiskBasedCache(getCacheDir(), 1024 * 1024); // 1MB cap
// Set up the network to use HttpURLConnection as the HTTP client.
Network network = new BasicNetwork(new HurlStack());
// Instantiate the RequestQueue with the cache and network.
mRequestQueue = new RequestQueue(cache, network);
// Start the queue
mRequestQueue.start();
// Formulate the request and handle the response.
StringRequest stringRequest = new StringRequest(Request.Method.POST, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// Do something with the response
Log.v("tesResponse","testResponseS");
Log.v("response",response);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// Handle error
Log.v("tesResponse","testResponseF");
Log.v("error",error.toString());
}
}
){
#Override
public String getBodyContentType() {
return "application/xml; charset=" +
getParamsEncoding();
}
#Override
public byte[] getBody() throws AuthFailureError {
String postData = payload;
try {
return postData == null ? null :
postData.getBytes(getParamsEncoding());
} catch (UnsupportedEncodingException uee) {
// TODO consider if some other action should be taken
return null;
}
}
};
// stringRequest.setRetryPolicy(new DefaultRetryPolicy(5*DefaultRetryPolicy.DEFAULT_TIMEOUT_MS, 0, 0));
stringRequest.setRetryPolicy(new DefaultRetryPolicy(0, 0, 0));
// Add the request to the RequestQueue.
mRequestQueue.add(stringRequest);
I have test the String url and the payload on POSTMAN and give successful result. But don't know why my android app give this error
08-22 19:44:24.335 16319-16518/com.example.victory1908.test1 D/OpenGLRenderer: Use EGL_SWAP_BEHAVIOR_PRESERVED: true
[ 08-22 19:44:24.355 16319:16319 D/ ]
HostConnection::get() New Host Connection established 0x7f67de64eac0, tid 16319
[ 08-22 19:44:24.399 16319:16518 D/ ]
HostConnection::get() New Host Connection established 0x7f67de64edc0, tid 16518
08-22 19:44:24.410 16319-16518/com.example.victory1908.test1 I/OpenGLRenderer: Initialized EGL, version 1.4
08-22 19:44:24.662 16319-16319/com.example.victory1908.test1 V/tesResponse: testResponseF
08-22 19:44:24.662 16319-16319/com.example.victory1908.test1 V/error: com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: Handshake failed
Just notice problem only with API 23+ (android 6.0 and above) API 22 is working fine!
I have tried set the retry policy but does not work. Anyone know what wrong with the code. Thanks in advance

How to get access_token of Exact Online API using apache OAuth 2.0

We are trying to use Exact Online API. It is using Apache OAuth 2.0 framework. For that we followed the below document.
https://developers.exactonline.com/#OAuth_Tutorial.html%3FTocPath%3DAuthentication%7C_____2
I successfully able to get the authorization code but failing to get the access_token with exception like below.
OAuthProblemException{error='invalid_request', description='Missing parameters: access_token', uri='null', state='null', scope='null', redirectUri='null', responseStatus=0, parameters={}}
My code is like this.
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
try {
OAuthAuthzResponse oar = OAuthAuthzResponse.oauthCodeAuthzResponse(request);
String code = oar.getCode();
OAuthClientRequest oAuthrequest = OAuthClientRequest
.tokenLocation("https://start.exactonline.co.uk/api/oauth2/token")
.setGrantType(GrantType.AUTHORIZATION_CODE)
.setClientId("my client id")
.setClientSecret("my client secret")
.setRedirectURI("http://localhost:8080/SampleServlet/AuthServlet")
.setCode(code)
.buildBodyMessage();
OAuthClient oAuthClient = new OAuthClient(new URLConnectionClient());
GitHubTokenResponse oAuthResponse = oAuthClient.accessToken(oAuthrequest, "POST",GitHubTokenResponse.class);
out.println("Access Token = " + oAuthResponse.getAccessToken());
} catch (OAuthSystemException ex) {
Logger.getLogger(AuthServlet.class.getName()).log(Level.SEVERE, null, ex);
} catch (OAuthProblemException ex) {
Logger.getLogger(AuthServlet.class.getName()).log(Level.SEVERE, null, ex);
} finally {
out.close();
}
}
Can some one please help me to sort this out.
Finally i resolved this issue with a simple change. The problem is with the line
GitHubTokenResponse oAuthResponse = oAuthClient.accessToken(oAuthrequest, "POST",GitHubTokenResponse.class);
Instead of this we have to use either of the below lines to get the access token properly.
OAuthJSONAccessTokenResponse oAuthResponse = oAuthClient.accessToken(oAuthrequest, OAuth.HttpMethod.POST);
(Or)
OAuthAccessTokenResponse oAuthResponse =oAuthClient.accessToken(oAuthrequest,OAuth.HttpMethod.POST);

Resources