I created google app in developer console.
Enable Admin SDK
Enable API access
In "Manage OAuth Client access" i added "Authorized API client" with
"https://www.googleapis.com/auth/admin.directory.user" scope.
Further, i want to get users from my domain.
JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
ArrayList<String> scopeList = new ArrayList<>();
scopeList.add(DirectoryScopes.ADMIN_DIRECTORY_USER_READONLY);
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId("bla-bla#developer.gserviceaccount.com")
.setServiceAccountScopes(scopeList)
.setServiceAccountPrivateKeyFromP12File(new File("p12 file")))
.setServiceAccountUser("superadmin#my-domain.com")
.build();
credential.setAccessToken("access token of current google user");
Directory admin = new Directory.Builder(httpTransport, JSON_FACTORY, credential)
.setApplicationName("Capsidea")
.setHttpRequestInitializer(credential).build();
return admin.users().list().setDomain("my-domain.com").execute();
All it's working when i login into google via OAuth by superadmin#my-domain.com.
But when i logined by some-user-non-admin#my-domain.com i have the error:
"Not Authorized to access this resource/api"
Can an non admin user to get a list of all users in the domain?
When the domain change this code will work given that it is necessary to specify superadmin'a ?
Any ideas?
setServiceAccountUser needs a user capable of Admin API usage (there is a fine-grained role configuration tool).
Do state that such a user is needed for your code to work.
Related
I brought up a GSuite Marketplace Listing with Service account created and Domain Wide Delegation enabled. I want to retrieve the users and orgunits of the customer.
Created a new Google Cloud Project
Enabled 'Admin SDK' in the project
Enabled 'GSuite Marketplace SDK', filled the scopes 'https://www.googleapis.com/auth/admin.directory.orgunit.readonly',
'https://www.googleapis.com/auth/admin.directory.user.readonly' and published the listing.
Enabled the 'Enable API Access' in the Admin Console of the customer.
The customer installed the app but I saw that the client_id of the SA was not added under the "Authorized API clients" section. When I try to retrieve the list of users in GSuite, I get the below error.
"unauthorized_client: Client is unauthorized to retrieve access tokens using this method, or client not authorized for any of the scopes requested"
Am I missing something in the marketplace listing ?
Why do you expect the SA's Oauth client to automatically appear under 'Authorized API Clients'? The instructions for setting up whitelisted Oauth clients for the domain mention you have to do it manually.
I am trying to connect to Azure DevOps previously known as VSTS using c#. I want to connect to it without the login screen of azure DevOps. I am currently trying the following code but some how it is not working
NetworkCredential netCred = new NetworkCredential("test#hotmail.com", "test");
Uri tfsuri = new Uri("https://dev.azure.com/test10");
VssBasicCredential bsCred = new VssBasicCredential(netCred);
VssCredentials vssCred = new VssClientCredentials(bsCred);
TfsTeamProjectCollection collection = new TfsTeamProjectCollection(tfsuri, vssCred);
collection.Authenticate();
var witClient = collection.GetClient<ProjectHttpClient>();
var listOfProjects = witClient.GetProjects().Result;
libraries I am using
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Core.WebApi;
using Microsoft.VisualStudio.Services.Client;
using Microsoft.VisualStudio.Services.Common;
using Microsoft.VisualStudio.Services.Operations;
using Microsoft.VisualStudio.Services.WebApi;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using Microsoft.TeamFoundation.WorkItemTracking.WebApi;
The code prompts a login screen, on which if I enter the password the auth still does not work. I dont want the login screen to appear and only want to connect with the username and password.
With alternate credentials this method is working but it is not my requirement and I can not use alternate credentials.
I have tried following the samples from the official site but no solution is working for the new DevOps.
Any Solution how can I authenticate with usernanme/password in the new DevOps without the login screen
The class TfsTeamProjectCollection is from the old .Net libraries, try the new Azure DevOps .Net libraries, and you can authenticate in a few ways:
NTLM
The most basic one is constructing a VssCredentials instance with no parameter at all and what you’ll be using is simply put integrated authentication / NTLM:
var visualStudioServicesConnection = new VssConnection(new Uri(baseUri), new VssCredentials());
Basic Authentication
VSTS and TFS also provide means to utilize Basic authentication (HTTP AUTH) which you need to create and enable first (see VSTS guidelines) and once you’ve done so, you can use them via the API like this:
var visualStudioServicesConnection = new VssConnection(new Uri(baseUri), new VssBasicCredential(username, password));
Personal Access Tokens
Next up are Personal Access Tokens (PAT) which you can easily create following the VSTS guidelines and those PATs are a means of authenticating separately from your actual credentials with a fine-grained & per access token scopes of security. Simply put it allows you to create a PAT for every use-case or even application and thereby enabling a secure and clearly separated way of giving an application or 3rd party access to your VSTS or TFS system on your behalf.
To use these via the API, you use the exact same mechanism as via Basic Authentication but you simply don’t provide any username (well – an empty one to be precise), and the PAT itself is used as the password:
var visualStudioServicesConnection = new VssConnection(new Uri(baseUri), new VssBasicCredential(string.Empty, pat));
Visual Studio Sign-in Prompt
Moreover, another way of authenticating is using the standard VS Sign-In prompt which is similarly easy and exposed via the VssClientCredentials class:
var visualStudioServicesConnection = new VssConnection(new Uri(baseUri), new VssClientCredentials());
OAuth Authentication
OAuth is a widely used but a slightly more tedious authorization protocol to implement but luckily there’s a thorough sample application available at CodePlex specifically for VSTS / VSO (which also works for on-premises).
Once you have the corresponding access token, you can use it to VSTS / TFS utilizing the VssOAuthCredential class:
var visualStudioServicesConnection = new VssConnection(new Uri(baseUri), new VssOAuthCredential(accessToken));
Azure Active Directory Authentication
Last but not least you can utilize Azure Active Directory identities to authenticate against a VSTS or TFS system via the VssAadCredential class:
var visualStudioServicesConnection = new VssConnection(new Uri(baseUri), new VssAadCredential(username, password));
I'd like to create a Service Account so I'd be able to authenticate with it with my app.
All I found is this guide, but it doesn't say how to create such an account.
Can anyone assist?
Thanks
The docs aren't that clear but a Service Account == App. So if you create an app in the developer console and set authentication type to server authentication (jwt) and add your public key and get the app authorized in the admin console then you're ready to instantiate a service account with the following code:
String privateKey = new String(Files.readAllBytes(Paths.get(PRIVATE_KEY_FILE)));
JWTEncryptionPreferences encryptionPref = new JWTEncryptionPreferences();
encryptionPref.setPublicKeyID(PUBLIC_KEY_ID);
encryptionPref.setPrivateKey(privateKey);
encryptionPref.setPrivateKeyPassword(PRIVATE_KEY_PASSWORD);
encryptionPref.setEncryptionAlgorithm(EncryptionAlgorithm.RSA_SHA_256);
IAccessTokenCache accessTokenCache = new InMemoryLRUAccessTokenCache(MAX_CACHE_ENTRIES);
// BoxDeveloperAPIConnection == Service Account
BoxDeveloperEditionAPIConnection api = BoxDeveloperEditionAPIConnection.getAppEnterpriseConnection(ENTERPRISE_ID, CLIENT_ID, CLIENT_SECRET, encryptionPref, accessTokenCache);
SOLUTION
I figured out how to solve this problem.
First of all here is my implementation with Service Account:
// Build service account credential.
GoogleCredential credential = new GoogleCredential.Builder().setTransport(httpTransport)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(Collections.singleton("https://www.googleapis.com/auth/appsmarketplace.license"))
.setServiceAccountPrivateKeyFromP12File(new File("/path/to/mykey/key.p12"))
// .setServiceAccountUser("NOT SET THIS LINE")
.build();
License build = new License.Builder(httpTransport, JSON_FACTORY, credential).setApplicationName("My Application").build();
Licenses execute = build.customerLicense().get("9999999999", "domain.test.com").execute();
This License Builder object is myself implementation based on the new google-api-client 1.17 and above. If someone could advice me how can i share with the rest of the community i will be glad to do it.
Best,
I have posted another thread, Google Apps Marketplace API customerLicense with OAuth2, explaining about my intentions to consume this API with OAuth2 Service Account strategy.
I have tried every method and officials library present and I always get Invalid OAuth header message or UNLICENSED
I am going to detail what is the scenery and what things i have tried:
I have and Google App Marketplace which use Service Account OAuth2 because all task are being perform on background.
This API Project has Service Account keys and Client Web Account keys too.
I published app restricted for my domain only because i am yet developing. So I installed App for my domain.
At this point it is suppose if I queried Customer License with API Project ID and Customer Id, which is domain name, I have to see the APP LICENSE for my domain.
I have used this jars https://developers.google.com/google-apps/marketplace/v2/developers_guide to access License API.
This is my code:
String appName = "MY APP";
AppsMarketService service = new AppsMarketService();
service.appId = "NUMBER_APP_ID";
service.appName = appName;
service.endpoint = "https://www.googleapis.com/appsmarket/v2/";
service.consumerKey = service.appId + ".apps.googleusercontent.com";
service.consumerSecret = "CLIENT_SECRET_FROM_WEB_OAUTH2_API_PROJECT";
service.authorize();
I get 403 forbidden if i use this code.
If i changed appId for prefix clientId from my API Project web OAuth2, I get 200 but with body UNLICENSED.
I have added scope to my app https://www.googleapis.com/auth/appsmarketplace.license and i still get the same result.
I have tried also getting Access Token from Admin user with Service Account handshake and then use that Oauth2 Access Token to access API License and the same result Invalid OAuth Token
My questions are:
Is there any way to access this API with Services Account keys, taking into consideration there is not consumer Secret in Service Accounts keys, only Client ID and private Key file?
Is there any updated library to use this with OAuth2 because i am seeing all this libraries are using OAuth1 with two-legged auth?
It would be great if someone can help me because we are trying to migrate our 7 Google App Old Marketplace Apps from OAuth1 to OAuth2 as per Google request but we have some black holes in our implementation if we would not be able to query what domains have our App Installed.
Best,
There is no need for any other libraries than OAuth2 lib. You can impmement this using urlfetch.
...
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.appengine.api.urlfetch.FetchOptions.Builder;
import com.google.appengine.api.urlfetch.HTTPHeader;
import com.google.appengine.api.urlfetch.HTTPMethod;
import com.google.appengine.api.urlfetch.HTTPRequest;
import com.google.appengine.api.urlfetch.HTTPResponse;
import com.google.appengine.api.urlfetch.URLFetchServiceFactory;
...
String SERVICE_ACCOUNT_EMAIL = "...#developer.gserviceaccount.com";
String P12 = "...-privatekey.p12";
// appid is the same id that you have in the google cloud project that has the Google Apps Marketplace API and SDK enabled
String appid = "";
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(new NetHttpTransport())
.setJsonFactory(new JacksonFactory())
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(Collections.singleton("https://www.googleapis.com/auth/appsmarketplace.license"))
.setServiceAccountPrivateKeyFromP12File(new File(P12))
.build();
credential.refreshToken();
String token = credential.getAccessToken();
URL url = new URL("https://www.googleapis.com/appsmarket/v2/licenseNotification/"+appid);
HTTPRequest request = new HTTPRequest(url, HTTPMethod.GET, Builder.allowTruncate());
request.setHeader(new HTTPHeader("Authorization", "Bearer "+token));
HTTPResponse response = URLFetchServiceFactory.getURLFetchService().fetch(request);
You need to install the OAuth2 package for this to work. In eclipse its under Google > Add Google Apis.
We've been working on an Google Apps-app meant to be installed by a domain administrator. We initially tried to list it via the (now deprecated) market listing, but all new submissions must now go through the Google Apps Marketplace SDK.
We're having an issue with the new GAM SDK SSO however - despite having installed it on our domain internally, each user is prompted via the consent screen when sending them to the OAuth login url. The OAuth url is asking for the same permission scope as is registered in the GAM SDK configuration screen.
The docs seem to be entirely conflicting on how to pull off non-challenged SSO for apps installed by the GA admin.
What url, with what params, we should be sending users to authenticate with GA without being asked for (presumably already granted) consent?
Can you share the code with which you are asking for authorization?
9 out of 10 times, if each user in the domain is getting prompted, that is because you are asking for "offline" access. Domain wide authorization cannot be done for offline access. In Python for instance, you can do that like this -
constructor_kwargs = {
'redirect_uri': GOOGLE_AUTH_CALLBACK_URL,
'auth_uri': client_info['auth_uri'],
'token_uri': client_info['token_uri'],
'access_type' : 'online'
}
flow = OAuth2WebServerFlow(client_info['client_id'],
client_info['client_secret'],
SCOPES, **constructor_kwargs)