What is the easiest way to detect whether a user is logged in via google apps marketplace? - google-oauth

I have a web application which users log into using google oauth2.
I have a google apps marketplace listing for this application, and some portion of the google oauth2 users didn't need to grant permission to my application because their google apps domain administrator did it while installing the apps marketplace listing.
I'd like to be able to detect this second group of users, to analyze how frequently the apps marketplace listing is being used to log into my application. At the moment all google oauth2 logins look the same to my application.
Is there a simple API call I can make to find out whether the current user is in this group?

I use this code for finding out marketplace listing info for given appId and target domain:
InputStream p12File = Config.class.getResourceAsStream(Config.SERVICE_ACCOUNT_PRIVATE_KEY_RESOURCE_PATH);
PrivateKey serviceAccountPrivateKey = SecurityUtils.loadPrivateKeyFromKeyStore(SecurityUtils.getPkcs12KeyStore(), p12File, "notasecret", "privatekey", "notasecret");
JsonFactory jsonFactory = new JacksonFactory();
HttpTransport t = GoogleNetHttpTransport.newTrustedTransport();
GoogleCredential.Builder bgc = new GoogleCredential.Builder()
.setTransport(t)
.setJsonFactory(jsonFactory)
.setServiceAccountScopes(Collections.singleton("https://www.googleapis.com/auth/appsmarketplace.license"))
.setServiceAccountPrivateKey(serviceAccountPrivateKey)
.setServiceAccountId(Config.SERVICE_ACCOUNT_ID);
GoogleCredential gc = bgc.build();
String token = gc.getAccessToken();
if(token == null) {
gc.refreshToken();
token = gc.getAccessToken();
}
HttpGet request = new HttpGet("https://www.googleapis.com/appsmarket/v2/customerLicense/" + applicationId + "/" + customerDomain);
request.setHeader("Authorization", "Bearer " + token);
DefaultHttpClient client = new DefaultHttpClient(httpParams);
HttpResponse resp = client.execute(request);
// ... read API JSON response

Related

Get user profile details from Google using access token

We have mobile app developed in react native in which we have to implement Google and Facebook login. We have RN libraries using which we will get Facebook and Google user's profile details. But our requirement is like we need to just pass the access token to web api which is developed in asp.net core, and using the access token we have to verify the access token in asp.net core web api and fetch the user's profile details using Facebook or Google Apis.
It is working fine for Facebook api, below is the code for the same
var httpClient = new HttpClient { BaseAddress = new Uri("https://graph.facebook.com/v2.9/") };
var response = await httpClient.GetAsync($"me?access_token={token}&fields=id,name,email,first_name,last_name,age_range,birthday,gender,locale,picture");
Similarly, when we pass access token(id_token) for google, it is not working, and below is code for the same,
var token ="eyJhb.eyJpc....";
var httpClient1 = new HttpClient { BaseAddress = new Uri("https://www.googleapis.com/oauth2/v3/") };
var response1 = await httpClient1.GetAsync($"userinfo?access_token={token}");
Can anyone please assist me, how can we verify the access token and fetch the user's profile details?
Thanks In Advance.
You can verify your "id_token" and get some user profile details at the same time by making GET request to the next endpoint:
"https://oauth2.googleapis.com/tokeninfo?id_token=XYZ123".
var token ="eyJhb.eyJpc....";
var httpClient1 = new HttpClient { BaseAddress = new Uri("https://oauth2.googleapis.com/") };
var response1 = await httpClient1.GetAsync($"tokeninfo?id_token={token}");
as described in google documentation "https://developers.google.com/identity/sign-in/web/backend-auth" (Calling the tokeninfo endpoint) section.
However in case you want to access google api services:
"id_token" is not meant to be used to access google api services, then you will need to have an "access_token" not an "id_token", you can follow the next documentation for that :
"https://developers.google.com/identity/protocols/oauth2"

Google API - Authentication setup and .NET client

I'm trying to achieve two things from my C# client application using Google API.
List all users of my google directory
Get metadata of all emails for each user
It appears, however, that my service account configuration is giving me issues. This is what I have done.
Created project in console.cloud.google.com
Enabled Admin SDK and Gmail API from API's and Services
Created Service Account with Domain-Wide delegation and obtained credentials.json file.
4. On admin.google.com I went to Security / API Controls and manage Domain-wide delegation. From here I added new API Client from my Service Account client id and assigned the following scopes:
https://www.googleapis.com/auth/gmail.settings.basic
https://www.googleapis.com/auth/gmail.settings.sharing
https://www.googleapis.com/auth/admin.directory.user.readonly
Finally, when I want to try to retrieve users list I get error: Expected OAuth 2 access token, login cookie or other valid authentication credential
static void Main(string[] args)
{
using (var stream =
new FileStream("..\\..\\..\\credentials.json", FileMode.Open, FileAccess.Read))
{
var credential = GoogleCredential.FromFile("..\\..\\..\\credentials.json");
var dirservice = new DirectoryService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "testbuildingnomiproductname",
});
var listReq = dirservice.Users.List();
Users allUsers = listReq.Execute();
int counter = 0;
foreach (User myUser in allUsers.UsersValue)
{
Console.WriteLine("*" + myUser.PrimaryEmail);
counter++;
}
Console.WriteLine(counter);
Console.ReadKey();
}
}

Youtrack and RestSharp Permissions issue

I'm trying to create a youtrack client using RestSharp. I can log in, but when I try to get a project, I receive the following response:
{"value":"You do not have permissions to read project. You are logged in as ****"}
However, when I log into YouTrack on my browser, I can access the project and make changes, etc. Attached is my code (I am using RestSharp):
var client = new RestClient(Site);
var request = new RestRequest(String.Format("rest/user/login?login={0}&password={1}", Username, Password), Method.POST);
//reuse the client
client.CookieContainer = new System.Net.CookieContainer();
IRestResponse response = client.Execute(request);
var content = response.Content;
//returns <login>ok</login> - so it's logging in
Console.WriteLine("LOGIN \n" + content);
String projectId = "PW";
request = new RestRequest(String.Format("rest/admin/project/projectId={0}", projectId), Method.GET);
response = client.Execute(request);
content = response.Content;
Console.WriteLine("Get Project: \n\n" + content);
Is there something in the code I'm missing? Or is this a YouTrack setup issue that I need to take up with my administrator?
For future reference:
I do not have permissions for the /rest/admin resources, but I do have them for /rest/issue. These permissions can be set by the system administrator, if they check the "Groups" in their dashboard.

Office365 authentication without login redirection

I'm trying to load data from Office365 email without need for user interaction. I've created Azure App and I have Client ID and Client secret.
I also have user information (email + password).
I need to call Office365 API to download emails from mailbox. But I need application to download them in background without user interaction (redirecting to MS/Office365 login page) to get authenticated/logged into mailbox.
Is there any way how to do this only through Office API, without need of redirection?
Thanks for any info.
Yes, you are able to create a daemon service app using the Client Credential flow to authenticate the app.
Here is a code sample to retrieve the mails using Microsoft Graph SDK with this flow:
string clientId = "";
string clientsecret = "";
string tenant = "";
string resourceURL = "https://graph.microsoft.com";
string authority = "https://login.microsoftonline.com/" + tenant + "/oauth2/token";
string userMail = "user1#yourdomain.onmicrosoft.com";
var credential = new ClientCredential(clientId, clientsecret);
AuthenticationContext authContext =new AuthenticationContext(authority);
var authResult = await authContext.AcquireTokenAsync(resourceURL, credential);
var graphserviceClient = new GraphServiceClient(
new DelegateAuthenticationProvider(
(requestMessage) =>
{
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", authResult.AccessToken);
return Task.FromResult(0);
}));
var items = await graphserviceClient.Users[userMail].Messages.Request().OrderBy("receivedDateTime desc").GetAsync();
foreach (var item in items)
{
Console.WriteLine(item.Subject);
}
And we need to register the app on the Azure AD portal and grant the app Mail.Read scope like figure below:
Refer to here for more detail about calling Microsoft Graph in a service or daemon app

Refresh Token with Google API Java Client Library

I'm using the Google API Java Client http://code.google.com/p/google-api-java-client/ and am able to get the access token successfully for Android.
// Google Accounts
credential = GoogleAccountCredential.usingOAuth2(this, CalendarScopes.CALENDAR);
SharedPreferences settings = getPreferences(Context.MODE_PRIVATE);
credential.setSelectedAccountName(settings.getString(PREF_ACCOUNT_NAME, null));
As I'd like my web server to make offline API calls, I need a refresh token. I have been searching extensively and have not yet figured out how to do so.
Ideally, I'd prefer to use the Google API Java Client over the WebView to grab the refresh token (no need to enter a username or password).
Any help would be appreciated!
You can also do this by creating a refresh token configured to a OAuth 2.0 Client Id.
Go to https://console.developers.google.com/apis/credentials
Click 'Create Credential'.
Click 'OAuth client Id'.
Select 'Web application' > Give a name.
Add https://developers.google.com/oauthplayground to 'Authorized redirect URIs'.
Click Create.
You will need the ClientId and the Secret for next steps.
Then go to https://developers.google.com/oauthplayground/
Click 'AOuth 2.0 Configuration' on right upper corner.
Check 'Use your own OAuth credentials'.
Update 'OAuth Client ID' and 'OAuth Client secret' with client id and secret of above created OAuth 2.0 credential.
In Step 1 on left corner, Select all the necessary scopes.(Please note that unmatching scopes in request will return 'invalid_scopes'.)
Click 'Authorize APIs'. This will redirect you to a consent page to allow permissions.
In Step 2, click 'Exchange authorization code for tokens'
You will get an Access Token with a Refresh Token. We will need this Refresh Token for the next step.
You can use this access token to authenticate to services you specified in scopes.
Access Tokens are short lived and Refresh tokens expire after 24 hours unless it is not bound to a OAuth 2.0 client (We just made our refresh token to last until it is revoked by the user or expires due to 6 months inactivity).
You need to refresh the Access Token before it expires. Check out following example to see how.
public String getNewToken(String refreshToken, String clientId, String clientSecret) throws IOException {
ArrayList<String> scopes = new ArrayList<>();
scopes.add(CalendarScopes.CALENDAR);
TokenResponse tokenResponse = new GoogleRefreshTokenRequest(new NetHttpTransport(), new JacksonFactory(),
refreshToken, clientId, clientSecret).setScopes(scopes).setGrantType("refresh_token").execute();
return tokenResponse.getAccessToken();
}
clientId and clientSecret in above example refers to OAuth 2.0 client credentials.
You can create a 'GoogleCredential' with that like this
public Credential getCredentials() throws GeneralSecurityException, IOException, FileNotFoundException {
final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
// Load client secrets.
String CREDENTIALS_FILE_PATH = "/credentials.json"; //OAuth 2.0 clinet credentials json
InputStream in = DriveQuickstart.class.getResourceAsStream(CREDENTIALS_FILE_PATH);
if (in == null) {
throw new FileNotFoundException("Resource not found: " + CREDENTIALS_FILE_PATH);
}
GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
String clientId = clientSecrets.getDetails().getClientId();
String clientSecret = clientSecrets.getDetails().getClientSecret();
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setClientSecrets(clientId, clientSecret)
.build();
String refreshToken = "<REFRESH-TOKEN>"; //Find a secure way to store and load refresh token
credential.setAccessToken(getNewToken(refreshToken, clientId, clientSecret));
credential.setRefreshToken(refreshToken);
return credential;
}
You need to set the following when you initiate the authorization flow :
approval prompt = force
access type = offline
With these params set, google will return a refresh token and the library will deal with refreshes. This works for me :
new GoogleAuthorizationCodeFlow.Builder(HTTP_TRANSPORT, JSON_FACTORY, getClientCredential(),
Arrays.asList(SCOPES)).setCredentialStore(new OAuth2CredentialStore()).setAccessType("offline")
.setApprovalPrompt("force").build();