MuleSoft Google Calendar connector - mule

Is there any way to authenticate Mule google calendar connector with google service account so that I can avoid the access popup every time.

Look at Managing OAuth tokens, if you make the object store that handles these persistent, then it will reuse the access tokens rather than redirecting for authorisation each time: https://docs.mulesoft.com/mule-user-guide/v/3.4/using-a-connector-to-access-an-oauth-api#managing-oauth-tokens-optional

I found a simple solution to my question
public void Auth() {
try {
httpTransport = GoogleNetHttpTransport.newTrustedTransport();
credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(getConsumerKey())
.setServiceAccountPrivateKeyFromP12File(new File(getConsumerSecret()))
.setServiceAccountScopes(Arrays.asList(getScope())).build();
client = new Calendar.Builder(
httpTransport, JSON_FACTORY, credential)
.setApplicationName(getApplicationName()).build();
}
catch (Exception e) {
e.printStackTrace();
}
}
Just include above function in the exiting google calendar code and remove the token based authentication from the code.
This will work absolutely fine with service account of google.
Thanks

Related

GoogleCredential deprecation

We want to implement Google OAUTH to play nicely with our web-app based credentials. Flow starts on UI side, which shows user consent screen, and then we obtain a code. That code is then sent to our java based back-end to get refresh token.
At the moment we use this approach:
private Analytics getAnalytics(String refreshToken) throws Exception {
NetHttpTransport httpTransport =
GoogleNetHttpTransport.newTrustedTransport();
JsonFactory jsonFactory =
JacksonFactory.getDefaultInstance();
return new Analytics.Builder(
httpTransport,
jsonFactory,
new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setClientSecrets(clientId, clientSecret)
.build()
.setRefreshToken(refreshToken)
).build();
}
The problem in above is that GoogleCredential is deprecated. What is they non-deprecated way to do this?
We are using following lib:
com.google.apis.google-api-services-analytics:v3-rev20190807-1.30.10
Google Credential is not fully deprecated, it depends on the library you are using (com.google.auth:google-auth-library-oauth2-http:0.17.1 should still work)
An any case, as mentioned here the non-deprecated way is to use Google Auth Library for Java
There are samples for different ways to build the credentials - depending on your use case.

Not able to access Google REST Api using Service Account

I need to access Google's BigQuery REST Api Endpoints with Service Account using Http client library.
So, I tried the code provided in the article Using OAuth 2.0 for Server to Server Applications
It gives me the compilation error in the below line.
Algorithm.RSA256(null, privateKey)
Code below:
GoogleCredential credential = GoogleCredential
.fromStream(new FileInputStream("service_account.json"));
PrivateKey privateKey = credential.getServiceAccountPrivateKey();
String privateKeyId = credential.getServiceAccountPrivateKeyId();
try {
Algorithm algorithm = Algorithm.RSA256(null, privateKey);
String signedJwt = JWT.create().withKeyId(privateKeyId)
.withIssuer("123456-compute#developer.gserviceaccount.com")
.withSubject("123456-compute#developer.gserviceaccount.com")
.withAudience("https://firestore.googleapis.com/google.firestore.v1beta1.Firestore")
.withIssuedAt(new Date(now)).withExpiresAt(new Date(now + 3600 * 1000L)).sign(algorithm);
} catch (Exception e) {
e.printStackTrace();
}
Note:
Algorithm.RSA256() accept java.security.interfaces.RSAPrivateKey
whereas Google Api returns java.security.PrivateKey
Could anyone help me in this?
What I found out looking into the Implementation: The RSAPrivateKey inherits from PrivateKey, so if you cast it (maybe type-check first), then you should be good to go!

custom login module to access httpservletrequest in JBOSS EAP

I am developing a custom login module for jboss' jaas implementation. I would like to be able to access the HttpServletRequest object inside my login module. Does anyone know the best way to do this, if it's possible? I've been researching this, and so far I think I need to use a Callback of some kind, but I'm not sure.I found some WebSphere documentation that shows they have a WSServletRequestCallback that seems to be able to do this. Please suggest a simple example or documentation if jboss' jaas implementation have anything like this.
Update:
#kwart: As per your suggestion, I coded the following. Please suggest if this is the right way:
protected CallbackHandler _callbackHandler;
HttpServletRequest request = null;
ObjectCallback objectCallback = null;
Callback[] callbacks = new Callback[1];
callbacks[0] = objectCallback = new ObjectCallback("HttpServletRequest: ");
try
{
_callbackHandler.handle(callbacks);
}
catch (Exception e)
{
logger.logp(Level.SEVERE, CLASSNAME, METHOD_NAME, "Error handling callbacks", e);
}
try
{
if (objectCallback != null)
{
request = (HttpServletRequest) PolicyContext.getContext("javax.servlet.http.HttpServletRequest");
}
}
catch (PolicyContextException e) {
logger.logp(Level.SEVERE, CLASSNAME, METHOD_NAME, "Error getting request", e);
}
catch (Exception e)
{
logger.logp(Level.SEVERE, CLASSNAME, METHOD_NAME, "Exception occured augmenting JbossSubject", e);
}
You can use JACC PolicyContext to retrieve the HttpRequestObject in the LoginModule methods:
HttpServletRequest request = (HttpServletRequest) javax.security.jacc.PolicyContext
.getContext(HttpServletRequest.class.getName());
Update: Find sample usage in LoginModule here.
I got a solution from this site.
Used JSPI authentication. Configured an auth module in security domain in standalone as explained here .
Created a custom authenticator and a custom login module, configured the authenticator in jboss-web.xml and login module in security domain in standalone xml.
I jar'd them in a separate module and added that to jboss-deployment-structure.xml. Stored http request in ThreadLocal in the authenticator and retrieved it in my login module by simply reading the value stored in the Thread Local.

Implement Authentication for servlet on publish instance CQ5/AEM

I have a scenario and any suggestions in implementing that will be of great help. I have a servlet created on publish that will have POST requests coming from a lot of other third party applications. This servlet just stores the incoming posted data in JCR. I have successfully created this servlet but now the requirement is to make this servlet secured so that only applications hitting this servlet with particular username and password should be entertained.
What can I do to achieve this?
The way I would go for it:
Ask those 3rd party applications to send you the username and password so you can validate them on your servlet, then decide if you will allow or reject the request.
from the servlet calling (the 3rd party application)
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// ...
request.setAttribute("username", "a_valid_user");
request.setAttribute("password", "a_valid_password");
request.getRequestDispatcher("yourApp/YourServlet").forward(req, resp);
}
On your servlet:
String username = request.getParameter("username");
String password = request.getParameter("password");
if("a_valid_user".equals(username) && "a_valid_password".equals(password) {
// validate and go further
} else {
// do not process the request
}
The above example is valid just in case you can validate them on your side.
If this sample doesn't answer to your question, please provide more information about those 3rd party applications and the way you want to validate them.
You might consider using Google Client Library. I used it for authentication of users in an AEM publish instance. After the third party server is authenticated, you could use a separate AEM service account to handle POST processing.
Here' a SO post I made about integrating those libraries into AEM.
Google Client API in OSGI
With this you should be able set up authentication of the third party service account... as discussed here
https://developers.google.com/identity/protocols/OAuth2ServiceAccount
I haven't actually done server to server auth in AEM, but it should be possible. But in a separate project (non AEM) I've used the Google Client Library for authenticating Service Accounts.
I recommend to use a two step process:
Step 1: Authentication and generate a token, you can use 3rd party service also to generate token.
Step 2: Call your servlet with this token, the servlet will validate token first and then use post data.
Thanks everyone for your replies. In the end I implemented the below code for authentication in cq :
final String authorization = request.getHeader("Authorization");
if (authorization != null && authorization.startsWith("Basic")) {
StringTokenizer st = new StringTokenizer(authorization);
if (st.hasMoreTokens()) {
String basic = st.nextToken();
if (basic.equalsIgnoreCase("Basic")) {
String decodedStr = Base64.decode(st.nextToken());
LOGGER.info("Credentials: " + decodedStr);
int p = decodedStr.indexOf(":");
if (p != -1) {
String login = decodedStr.substring(0, p).trim();
String password = decodedStr.substring(p + 1).trim();
Credentials credentials = new SimpleCredentials(login, password.toCharArray());
adminSession = repository.login(credentials);
if (null != adminSession) {
// means authenticated and do your stuff here
}
}
}
}
}
Also in the webservice code which is calling the servlet of publish, below is the code on how I am supplying the credentials in auth headers :
String authStr = usrname+":"+password;
// encode data on your side using BASE64
byte[] bytesEncoded = Base64.encodeBase64(authStr.getBytes());
String authEncoded = new String(bytesEncoded);
connection.setRequestProperty("Authorization", "Basic "+authEncoded);
connection.setDoOutput(true);
connection.setRequestMethod("POST");
OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
writer.write("jsondata={sample:jsoncontent}");
writer.close();

ArgumentException: Precondition failed.: !string.IsNullOrEmpty(authorization.RefreshToken) with Service Account for Google Admin SDK Directory access

I'm trying to access the Google Directory using a Service Account. I've fiddled with the DriveService example to get this code:
public static void Main(string[] args)
{
var service = BuildDirectoryService();
var results = service.Orgunits.List(customerID).Execute();
Console.WriteLine("OrgUnits");
foreach (var orgUnit in results.OrganizationUnits)
{
Console.WriteLine(orgUnit.Name);
}
Console.ReadKey();
}
static DirectoryService BuildDirectoryService()
{
X509Certificate2 certificate = new X509Certificate2(SERVICE_ACCOUNT_PKCS12_FILE_PATH, "notasecret",
X509KeyStorageFlags.Exportable);
var provider = new AssertionFlowClient(GoogleAuthenticationServer.Description, certificate)
{
ServiceAccountId = SERVICE_ACCOUNT_EMAIL,
Scope = DirectoryService.Scopes.AdminDirectoryOrgunit.GetStringValue()
};
var auth = new OAuth2Authenticator<AssertionFlowClient>(provider, AssertionFlowClient.GetState);
return new DirectoryService(new BaseClientService.Initializer()
{
Authenticator = auth,
ApplicationName = "TestProject1",
});
}
When I run it, I get
ArgumentException: Precondition failed.: !string.IsNullOrEmpty(authorization.RefreshToken)
I'm going round in circles in the Google documentation. The only stuff I can find about RefreshTokens seems to be for when an individual is authorizing the app and the app may need to work offline. Can anyone help out or point me in the direction of the documentation that will, please.
Service Account authorization actually do not return Refresh Token - so this error makes sense. Do you know where this is coming from?
I am not too familiar with the .NET client library but having the full error trace would help.
As a longshot - The error might be a bad error -
Can you confirm that you've enabled the Admin SDK in the APIs console for this project
Can you confirm that you whitelisted that Client ID for the service account in the domain you are testing with (along with the Admin SDK scopes)
The above code will work if you replace the provider block with:
var provider = new AssertionFlowClient(GoogleAuthenticationServer.Description, certificate)
{
ServiceAccountId = SERVICE_ACCOUNT_EMAIL,
Scope = DirectoryService.Scopes.AdminDirectoryOrgunit.GetStringValue(),
ServiceAccountUser = SERVICE_ACCOUNT_USER //"my.admin.account#my.domain.com"
};
I had seen this in another post and tried it with my standard user account and it didn't work. Then I read something that suggested everything had to be done with an admin account. So, I created a whole new project, using my admin account, including creating a new service account, and authorising it. When I tried it, it worked. So, then I put the old service account details back in but left the admin account in. That worked, too.