Gsuite SDK Java密码重置引发超级管理员用户未经授权的访问

时间:2018-11-20 12:11:00

标签: java sdk gsuite

我有一个Java应用程序,允许用户重置GSuite的密码。我们不允许用户更改自己的密码,而是将他们重定向到Web应用程序,该应用程序允许他们更改两个Active Directory的密码,然后使用GSuite重置相同的密码。我遵循了复杂的安全方​​案,即在gsuite帐户中启用API,然后在Google Cloud环境中创建服务帐户,然后在GSuite中授权该服务帐户。我还在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

发生的事情是,当我尝试更改标准电子邮件用户的密码时,它可以正常工作,但是当我尝试以超级管理员角色重置密码时,它失败,并出现以下异常:

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!!");

    }
}

0 个答案:

没有答案