I’m working on a PHP web application that needs to connect to Google Drive API. The setup is a bit complex so let me explain what I’m trying to do.
First, users log into my app using their company Gmail accounts (like [email protected]). I use OAuth 2.0 for this login process and it works fine.
After login, the app should display and edit Google Sheets from a different account (something like [email protected]). I set up a service account and can modify spreadsheets, but I can’t see any files when listing them.
The result is always “No files detected” even though the target Drive has several documents. I think I need to configure domain-wide delegation but I’m not sure how to implement it properly. Any suggestions on what I’m missing?
Your service account code looks correct but you’re missing the crucial delegation step. I ran into this exact same problem last year when building a similar system. The service account has its own empty drive space by default, which explains the zero results. After setting up domain-wide delegation in your Google Workspace admin console, you need to specify which user account to impersonate. Add this line before creating your drive service: $googleClient->setSubject('[email protected]'); This tells the service account to act on behalf of that specific user. One gotcha I discovered during implementation - make sure your service account has the correct OAuth scopes configured in the admin console delegation settings. The scope should match exactly what you’re requesting in your PHP code. Also double check that your credentials JSON file contains the private key and client email properly. The delegation won’t work without both pieces configured correctly on both the code side and admin console side.
Had this exact scenario at my previous job and spent days debugging it. The core issue is that your service account creates its own isolated Drive instance rather than accessing the admin account’s files. You’ve got two paths forward here but there’s an important detail others missed - even with domain-wide delegation properly configured, you still need to ensure the service account email has been granted the necessary permissions in your Google Workspace admin console under Security > API Controls > Domain-wide Delegation. The client ID from your JSON credentials file must be added there with the drive scopes explicitly listed. Without this admin-level approval, the setSubject() method will fail silently and you’ll keep getting empty results. I’d also recommend testing with a more specific query parameter like q: "'[email protected]' in owners" to verify you’re actually accessing the right account’s files once delegation is working. The alternative sharing approach mentioned earlier works but becomes unwieldy if you need access to many files or folders.
The issue you’re encountering is related to how service accounts work with Google Drive. When you create a service account, it essentially gets its own isolated Google Drive that’s completely separate from any user’s drive. That’s why your listFiles() call returns empty results - you’re looking at the service account’s empty drive, not the [email protected] drive.
To access files from [email protected], you have two main approaches. First option is domain-wide delegation which requires G Suite admin privileges to set up. You’d need to enable it in the admin console and modify your code to impersonate the target user. Second approach is simpler but requires manual setup - have the [email protected] user directly share the needed folders/files with your service account email address (found in your credentials JSON file). The service account email looks something like [email protected].
I’d recommend trying the sharing approach first since it’s much easier to implement and doesn’t require admin console access. Just share the specific folders you need with the service account email and your current code should start seeing those files.
domain-wide delegation is definetly what you need here but theres a missing piece in your setup. you need to add setSubject() to impersonate the admin user. after setting up delegation in admin console, modify your client like this: $googleClient->setSubject('[email protected]'); before creating the drive service. without this your still accessing the service accounts empty drive instead of the admins files.