У меня есть приложение на Java, которое позволяет пользователям сбросить свой пароль для GSuite.Мы не разрешаем пользователям изменять свой собственный пароль, вместо этого мы перенаправляем их в веб-приложение, которое позволяет им изменять свой пароль для обоих каталогов Active Directory, а затем сбрасывать тот же пароль с помощью GSuite.Я следовал сложной схеме безопасности: включил API в учетной записи gsuite, а затем создал учетную запись службы в среде Google Cloud и затем авторизовал учетную запись службы в GSuite.Я также добавил пользователя superadmin в Gsuites, который будет использоваться для этого сервиса.Помните, что служба работает в серверной части на сервере и не может использовать интерактивную авторизацию OAauth.Учетной записи службы были предоставлены следующие разрешения:
https://www.googleapis.com/auth/admin.directory.group
https://www.googleapis.com/auth/admin.directory.user
https://www.googleapis.com/auth/admin.directory.user.readonly
https://www.googleapis.com/auth/admin.directory.user.security
То, что происходит, когда я пытаюсь изменить пароль для обычного пользователя электронной почты, работает нормально, но когда я пытаюсь сбросить пароль с помощью superadminроль, он завершается со следующим исключением:
Exception in thread "main" com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
{
"code" : 403,
"errors" : [ {
"domain" : "global",
"message" : "Not Authorized to access this resource/api",
"reason" : "forbidden"
} ],
"message" : "Not Authorized to access this resource/api"
}
at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:150)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:113)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:40)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest$1.interceptResponse(AbstractGoogleClientRequest.java:401)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1056)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:499)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:432)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:549)
at gsuite.updateDirectory(gsuite.java:111)
at gsuite.changePassword(gsuite.java:53)
at gsuite.main(gsuite.java:118)
Вот полный источник:
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.jackson.JacksonFactory;
import com.google.api.services.admin.directory.Directory;
import com.google.api.services.admin.directory.DirectoryScopes;
import com.google.api.services.admin.directory.model.User;
import com.google.api.services.admin.directory.model.Users;
import javax.xml.bind.DatatypeConverter;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
public class gsuite {
/**
* Email of the Service Account
*/
private static final String SERVICE_ACCOUNT_EMAIL = "webapp@transactrxsecurity.iam.gserviceaccount.com";
private static Directory directory=null;
/**
* Path to the Service Account's Private Key file
*/
private static final String SERVICE_ACCOUNT_PKCS12_FILE_PATH = "/Users/manuelelaraj/Downloads/transactrxsecurity-0ad733208988.p12";
private static final String DOMAIN_NAME="somedomain.com";
private static final String SUPER_USER_EMAIL = "system@Somedomain.com";
private static final String SUPER_USER_PASSWORD="Strongpassword";
public static void changePassword( Directory dir, final String username, final String newPassword ) throws Exception
{
Users users=getGSuiteUser( dir, DOMAIN_NAME, username );
if (users.isEmpty())
{
}
final User UserToBeUpdated = updatePassword( users.getUsers().get(0), SUPER_USER_PASSWORD);
updateDirectory( dir, UserToBeUpdated );
}
private static Directory getDirectory() throws IOException, GeneralSecurityException, URISyntaxException
{
if (directory!=null)
{
return directory;
}
final NetHttpTransport httpTransport = new NetHttpTransport();
final JacksonFactory jsonFactory = new JacksonFactory();
final File p12 = new File( SERVICE_ACCOUNT_PKCS12_FILE_PATH );
final GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountUser( SUPER_USER_EMAIL )
.setServiceAccountId( SERVICE_ACCOUNT_EMAIL ) //the one that ends in "@developer.gserviceaccount.com"
.setServiceAccountScopes( getCredentials() )
.setServiceAccountPrivateKeyFromP12File( p12 )
.build();
directory= new Directory.Builder( httpTransport, jsonFactory, null)
.setHttpRequestInitializer( credential )
.setApplicationName( "API Project" ) //Not necessary, but silences a runtime warning using any not-blank string here
.build();
return directory;
}
private static List<String> getCredentials()
{
final List<String> toReturn = new LinkedList<String>();
toReturn.add( DirectoryScopes.ADMIN_DIRECTORY_GROUP );
toReturn.add( DirectoryScopes.ADMIN_DIRECTORY_USER );
toReturn.add( DirectoryScopes.ADMIN_DIRECTORY_USER_READONLY );
toReturn.add( DirectoryScopes.ADMIN_DIRECTORY_USER_SECURITY );
return toReturn;
}
private static Users getGSuiteUser( final Directory dir, final String domain, final String username ) throws Exception
{
Directory.Users.List diruserlist = dir.users().list()
.setDomain( domain )
.setQuery( "email:" + username );
return diruserlist.execute();
}
private static User updatePassword( final User user, final String password ) throws Exception
{
final MessageDigest md = MessageDigest.getInstance( "MD5" ); //I've been warned that this is not thread-safe
final byte[] digested = md.digest( password.getBytes( "UTF-8" ) );
final String newHashword = DatatypeConverter.printHexBinary( digested );
return user.setHashFunction("MD5") //only accepts MD5, SHA-1, or CRYPT
.setPassword( newHashword );
}
private static void updateDirectory( final Directory dir, final User user ) throws IOException
{
final Directory.Users.Update updateRequest = dir.users().update( user.getPrimaryEmail(), user );
updateRequest.execute();
}
public static void main(String[] args) throws Exception {
Directory dir=getDirectory();
//regular user works!!
changePassword(dir,"userwithsuperadmin@transactrx.com","MaherManuco99!!");
//changing password for admin fails!!!
changePassword(dir,"userwithsuperadmin@transactrx.com","MaherManuco99!!");
}
}