Unable to generate access token from grant token in zoho - zoho

I have registered the application and generate clientId, clientsceret, code from the application.
I have configured and initialize it but unable to generate access token.
This is my code:
ZohoOAuthClient client = ZohoOAuthClient.GetInstance();
string grantToken = "1000.fd54383a88527ee4a9dfd589f4bba161.95bdbba47dffb77a5d830b2561b2d7a3";
ZohoOAuthTokens tokens = client.GenerateAccessToken(grantToken);
string accessToken = tokens.AccessToken;
string refreshToken = tokens.RefreshToken;
I'm getting error of "error": "invalid_code"

You may need to initialize the RestClient before instantiating and calling to GenerateAccessToken
ZCRMRestClient.initialize();

Related

What are the difference between scope "IMAP.AccessAsUser.All" and "https://outlook.office365.com/IMAP.AccessAsUser.All" of MSAL?

I want to get access token to get access to Outlook by IMAP using MSAL.
The code used to get the access token is below(written by Kotlin).
fun getAccessTokenByMSAL(
appId: String,
scopes: List<String>
): String? {
val scopeSet = HashSet<String>()
scopes.stream().forEach { scope ->
scopeSet.add(scope)
}
val app = PublicClientApplication
.builder(appId)
.authority("https://login.microsoftonline.com/common")
.build();
val params = InteractiveRequestParameters
.builder(URI("http://localhost:8080"))
.scopes(scopeSet)
.build()
val result = app.acquireToken(params).join()
return result.accessToken()
}
To get access to Outlook by IMAP, I want to add "IMAP.AccessAsUser.All" permission as scope like below.
val scopes = listOf(
"https://outlook.office365.com/IMAP.AccessAsUser.All",
)
val token = getAccessTokenByMSAL(appId, scopes)
However, as a result, when I try to log in with my personal account, I get the following error message in my browser (The error message has no embedded character string and is displayed strangely.):
Authentication failed. You can return to the application. Feel free to close this browser tab.
Error details: error {0} error_description: {1}
When I change scope as follows and try again, then authentication success.
val scopes = listOf(
"IMAP.AccessAsUser.All"
)
val token = getAccessTokenByMSAL(appId, scopes)
So, what are the difference between scope "IMAP.AccessAsUser.All" and "https://outlook.office365.com/IMAP.AccessAsUser.All"?
And which is correct to get right access token to connect Outlook by IMAP?
It's a mess.
IMAP.AccessAsUser.All
E.g.,
https://graph.microsoft.com/IMAP.AccessAsUser.All
Is a Microsoft Graph audience scope, but it seems its completely useless client-side, and is only used when adding scopes to your app.
On the other hand,
https://outlook.office365.com/IMAP.AccessAsUser.All
Is the scope you have to request client-side, if you want to access Exchange mailboxes using IMAP with OAuth 2.0.
You can't add it to your application scopes, but if you add:
https://graph.microsoft.com/IMAP.AccessAsUser.All
It allows you to request both of the following:
https://graph.microsoft.com/IMAP.AccessAsUser.All https://outlook.office365.com/IMAP.AccessAsUser.All
I'm talking from my experience trying to access Exchange Enterprise (in-tenant) mailboxes via IMAP with OAuth 2.0. It could be different for personal and school accounts.

Login to web server with Google Sign-in

I'm connecting to a 3rd party web server from an HTTP client (Java or Dart - Android app) to download some resources (XML or IMG files) that belong to the current user on that server. This site requires login with Google Sing-In. I have everything set up in my Android app to login the user with Google, I obtained their authorization idToken. But how do actually use it in HTTP GET or POST methods to download the protected resources?
With BASIC authentication it's easy - just set HTTP 'Authorization' header correctly ("Basic " + user:password encoded as base64), call GET, and I download the desired resource. But I cannot find any information on how to do this with Google Sing-In. Do I send the idToken I received from Google in some headers? What other magic is needed?
Adding a Java code snippet, hope it helps:
// (Receive authCode via HTTPS POST)
if (request.getHeader('X-Requested-With') == null) {
// Without the `X-Requested-With` header, this request could be forged. Aborts.
}
// Set path to the Web application client_secret_*.json file you downloaded from the
// Google API Console: https://console.developers.google.com/apis/credentials
// You can also find your Web application client ID and client secret from the
// console and specify them directly when you create the GoogleAuthorizationCodeTokenRequest
// object.
String CLIENT_SECRET_FILE = "/path/to/client_secret.json";
// Exchange auth code for access token
GoogleClientSecrets clientSecrets =
GoogleClientSecrets.load(
JacksonFactory.getDefaultInstance(), new FileReader(CLIENT_SECRET_FILE));
GoogleTokenResponse tokenResponse =
new GoogleAuthorizationCodeTokenRequest(
new NetHttpTransport(),
JacksonFactory.getDefaultInstance(),
"https://www.googleapis.com/oauth2/v4/token",
clientSecrets.getDetails().getClientId(),
clientSecrets.getDetails().getClientSecret(),
authCode,
REDIRECT_URI) // Specify the same redirect URI that you use with your web
// app. If you don't have a web version of your app, you can
// specify an empty string.
.execute();
String accessToken = tokenResponse.getAccessToken();
// Use access token to call API
GoogleCredential credential = new GoogleCredential().setAccessToken(accessToken);
Drive drive =
new Drive.Builder(new NetHttpTransport(), JacksonFactory.getDefaultInstance(), credential)
.setApplicationName("Auth Code Exchange Demo")
.build();
File file = drive.files().get("appfolder").execute();
// Get profile info from ID token
GoogleIdToken idToken = tokenResponse.parseIdToken();
GoogleIdToken.Payload payload = idToken.getPayload();
String userId = payload.getSubject(); // Use this value as a key to identify a user.
String email = payload.getEmail();
boolean emailVerified = Boolean.valueOf(payload.getEmailVerified());
String name = (String) payload.get("name");
String pictureUrl = (String) payload.get("picture");
String locale = (String) payload.get("locale");
String familyName = (String) payload.get("family_name");
String givenName = (String) payload.get("given_name");
For detailed info, find all the required steps and references at: https://developers.google.com/identity/sign-in/web/server-side-flow#step_1_create_a_client_id_and_client_secret

Oauth2 Spring Security Resource Server and Independent Auth Server

everyone!
I'm new to Oauth2 and I've had different approaches with it.
I have a doubt. I'm actually building a Provider Server with Spring Security and I have an external access token provider (Google and AWS Cognito).
I know the process to get the access token following the code grant flow (Which is the one I want to implement). I built an Android app that gets the code and changes it for the access token.
My question is:
How do I validate that the token I'm sending to the Provider Server is a valid one using Spring Security to also access the protected resources that the server has?
Thank you in advance.
I think there are two alternatives either u get the public key and verify the token urself or maybe they have an endpoint where you can send the token and know if its a valid one or not.
Something like this
GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory)
// Specify the CLIENT_ID of the app that accesses the backend:
.setAudience(Collections.singletonList(CLIENT_ID))
// Or, if multiple clients access the backend:
//.setAudience(Arrays.asList(CLIENT_ID_1, CLIENT_ID_2, CLIENT_ID_3))
.build();
// (Receive idTokenString by HTTPS POST)
GoogleIdToken idToken = verifier.verify(idTokenString);
if (idToken != null) {
Payload payload = idToken.getPayload();
// Print user identifier
String userId = payload.getSubject();
System.out.println("User ID: " + userId);
// Get profile information from payload
String email = payload.getEmail();
boolean emailVerified = Boolean.valueOf(payload.getEmailVerified());
String name = (String) payload.get("name");
String pictureUrl = (String) payload.get("picture");
String locale = (String) payload.get("locale");
String familyName = (String) payload.get("family_name");
String givenName = (String) payload.get("given_name");
// Use or store profile information
// ...
} else {
System.out.println("Invalid ID token.");
}
Link: https://developers.google.com/identity/sign-in/web/backend-auth

PlatformPlugin exception getting app-only token using MSAL in ASP.NET Core

I'm trying to create an ASP.NET Core app that uses MSAL for the client credentials flow.
I get the following exception when trying to get an access token:
NullReferenceException: Object reference not set to an instance of an object.
Microsoft.Identity.Client.Internal.PlatformPlugin.LoadPlatformSpecificAssembly()
Authentication is modeled after this sample: active-directory-dotnet-webapp-openidconnect-aspnetcore-v2
Authorization is modeled after this sample: active-directory-dotnet-daemon-v2
My app is registered with the Mail.Read Application permission. Here's the code that throws the exception:
string authority = $"https://login.microsoftonline.com/{ tenantId }/v2.0";
ConfidentialClientApplication client = new ConfidentialClientApplication(
authority,
appId,
redirectUri,
new ClientCredential(appSecret),
null);//new TokenCache());
AuthenticationResult authResult = await client.AcquireTokenForClient(
new string[] { "Mail.Read" }, null);
return authResult.Token;
Also tried with "https://graph.microsoft.com/.default" scope, as in the daemon sample.
Answering this question. I opened this as an issue on the GitHub repo. It was closed with the following response:
this problem will not occur with the next release as we will move to a single binary.

Call SharePoint online REST API from azure API

I have developed a Azure API protected with AAD , which is working fine,
now I would like to call SharePoint online REST API from my Azure API ,my SharePoint online is using same active directory as my azure API.
For calling SP API i need access token to authenticate SharePoint
I assume the access token which authenticated the Azure API would be same to call SharePoint API
this is what I did :
My Azure API is registered in azure active directory (which is automatically done which I made authentication on )
I updated the Azure app's manifest.json to enable oauth2 implicit flow:
"oauth2AllowImplicitFlow": true
I granted the app access to "Read and write items and lists in all site collections" on behalf of the user (under delegated permissions) from the Azure AD app settings page ("permissions to other applications").
I tried to this code to get access token :
string clientId = "xxxxxxxxxx";
string appKey = xxxxxxxxxxx";
string aadInstance = "https://login.microsoftonline.com";
string tenant = "mydomain.onmicrosoft.com";
string domain = "mydomain.onmicrosoft.com";
string resource = "https://mydomain.sharepoint.com";
AuthenticationResult result = null;
ClientCredential clientCred = new ClientCredential(clientId, appKey);
string authHeader = HttpContext.Current.Request.Headers["Authorization"];
string userAccessToken = authHeader.Substring(authHeader.LastIndexOf(' ')).Trim();
UserAssertion userAssertion = new UserAssertion(userAccessToken);
string authority = aadInstance + domain;
AuthenticationContext authContext = new AuthenticationContext(authority);
//result = await authContext.AcquireTokenAsync(resource, clientCred); // auth without user assertion (fails, app only not allowed)
result = await authContext.AcquireTokenAsync(resource, clientCred, userAssertion); // clientCred and userAssertion params have swapped places since Kirk's blog
return result.AccessToken;
but authHeader is null ,
I came across this question which mentions in order to retrieve a user token uses ADAL.js using authenticationContext.acquireToken(clientId), then include the resulting token in the header of the AJAX request to the WebAPI
I am not sure how i need to include this in my azure API
anyway i appreciate any thoughts or idea to get access token to run SharePoint online APIs behalf of logged in user in azure API

Resources