Сброс пароля Java Gsuite SDK создает несанкционированный доступ для пользователей superadmin - PullRequest
0 голосов
/ 20 ноября 2018

У меня есть приложение на 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!!");

    }
}
...