4

My org is new to Google Auth and we have poured countless hours into documentation readings. The mission was simple: view members in our google groups through the Directory API.

Our setup: The cloud function deploys and runs with a service account that has been granted domain-wide access with the proper scopes, and impersonates an admin user detailed here:

https://developers.google.com/admin-sdk/directory/v1/guides/delegation

When I run the function locally and pull the service account key from a file path I get the error: "Error 403: Not Authorized to access this resource/api, forbidden"

I noticed that when deploying the Cloud Function via inline text or an uploaded zip it was unable to read a .json or .text file type when I included it in the package. I know this is bad practice but just to see I put in marshaled the JSON key in the main file.

And still got a "Error 403: Not Authorized to access this resource/api, forbidden"

Where am I going wrong?

import (
    "encoding/json"
    "fmt"
    _"io/ioutil"
    "log"
    "net/http"
    _ "os"
    "time"

    "golang.org/x/net/context"
    "golang.org/x/oauth2/google"

    admin "google.golang.org/api/admin/directory/v1"
    "google.golang.org/api/option"
)


var User_email = <user>


func createAdminDirectoryService(serviceAccountFilePath, gsuiteAdminUserEmail string) *admin.Service {
    jsonCredentials,_ := json.Marshal(map[string]string{<SERVICE KEY FILE>})

    log.Println("Json creds: ", jsonCredentials)

    config, err := google.JWTConfigFromJSON(
        jsonCredentials,
        "https://www.googleapis.com/auth/admin.directory.group.member.readonly",
    )
    if err != nil {
        log.Printf("Json Config error:%v", err.Error())
    }
    config.Subject = gsuiteAdminUserEmail

    fmt.Println(serviceAccountFilePath)//vestigial of previous version reading key from file
    fmt.Println(gsuiteAdminUserEmail)

    ctx, _ := context.WithDeadline(context.Background(), time.Now().Add(20*time.Second))
    ts := config.TokenSource(ctx)

    srv, err := admin.NewService(ctx, option.WithTokenSource(ts))
    if err != nil {
        log.Println("Admin Service error:", err.Error())
    }
    return srv
}

func listUsersInGroup(srv *admin.Service, groupEmail string) ([]string, error) {
    membersEmails := make([]string, 1)
    members, err := srv.Members.List(groupEmail).Do()
    if err != nil {
        log.Fatal("fatalerror list users: ", err)

        membersEmails[0] = "Nope"

    } else {
        membersEmails := make([]string, len(members.Members))
        for i, member := range members.Members {
            membersEmails[i] = member.Email
        }
    }

    return membersEmails, err
}

func Main(w http.ResponseWriter, r *http.Request) {

    groupEmail := <groupemail>
    path := "./key.json" //vestigial of previous version reading key from file
    fmt.Println("Path:", path)

    srv := createAdminDirectoryService(
        path,
        User_email,
    )

    members, err := listUsersInGroup(srv, groupEmail)

    if err != nil {
        log.Println(members)
    } else {
        log.Println("sorry bud")
    }
}
   
  • 2
    Try adding all these [scopes](https://developers.google.com/admin-sdk/directory/reference/rest/v1/members/list#authorization-scopes) in your code and the Admin console where you added the service account. As a reference, here is an [example](https://developers.google.com/admin-sdk/directory/v1/guides/delegation#instantiate_an_admin_sdk_directory_service_object) with Go using a JSON-formatted key file. Also, are you impersonating a Super Admin and is this a recent admin? Additionally, the user must have logged in at least once and accepted the Google Workspace Terms of Service. – Lorena Gomez Apr 22 '22 at 20:33
  • @LorenaGomez Thank you for taking the time to reply! I linked the same example in my post because I used it as a reference. As stated above my issue is that the Cloud Function can't read a .JSON file attached to the project. So I modified it to read the JSON key as an array. However both locally and on the cloud function I get a 403 error. I do impersonate a super admin who has had access for years. The google.JWTConfigFromJSON method only accepts one scope, which is odd and annoying. I will poke around and see if I can add more. – Tiara Porter Apr 26 '22 at 14:45
  • another thing to check when getting this type of error, make sure that the Admin SDK is enabled for your project in the Google Cloud Platform console, you can check that through this [link](https://console.cloud.google.com/apis/library/admin.googleapis.com). Also, if you test with the "[Directory API](https://developers.google.com/admin-sdk/directory/reference/rest/v1/members/list)" with the same admin does that works or do you get the same error? – Lorena Gomez Apr 27 '22 at 01:12

0 Answers0