When I use a client secret authentication flow with a confidential client, how could I authenticate a user (one that connects as an HTTP client to my website, or any other method of network access) and use delegated access?
I understand how to do so with a public client. I could also use a public client flow on this server, but that would make little sense as my server should technically be a confidential client.
Minimal working example (if "MY.\{-}"
is replaced with valid a valid set of client secret, client ID, and tenant ID):
package main
import (
"context"
"fmt"
"github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential"
)
func main() {
cred, err := confidential.NewCredFromSecret("MY_CLIENT_SECRET")
if err != nil {
panic(err)
}
confidential_client, err := confidential.New(
"https://login.microsoftonline.com/"+"MY_TENANT_ID",
"MY_CLIENT_ID",
cred,
)
if err != nil {
panic(err)
}
result, err := confidential_client.AcquireTokenByCredential(
context.Background(),
[]string{"User.Read"},
)
if err != nil {
panic(err)
}
fmt.Println(result)
}
Results:
{
"error": "invalid_scope",
"error_description": "AADSTS1002012: The provided value for scope User.
Read openid offline_access profile is not valid. Client credential flows must have a scope value with /.default suffixed to the resource identifier (application ID URI). Trace ID: REDACTED Correlation ID: REDACTED Timestamp: 2024-08-16 03:46:42Z",
"error_codes": [1002012],
"timestamp": "2024-08-16 03:46:42Z",
"trace_id": "REDACTED",
"correlation_id":"REDACTED"
}
Note that: Confidential client only works with Application type API permissions and with no user interaction involved.
For sample, I tried to generate token via postman and got the same error as you:
https://login.microsoftonline.com/TenantID/oauth2/v2.0/token
client_id:ClientID
client_secret:ClientSecret
scope↵:https://graph.microsoft.com/.default
grant_type:client_credentials
The error "The provided value for scope User.Read is not valid. Client credential flows must have a scope value with /.default suffixed to the resource identifier (application ID URI)" usually occurs if the scope while using Confidential client is not suffixed by /.default. To resolve the error use https://graph.microsoft.com/.default
Confidential client doesn't suit your scenario as you want to pass scope as User.Read
and do not want to pass client secret you can make use of public client flow.
If there is user interaction involved, and you want to retrieve details of the signed in user then you need to make use of any user interactive flow.
It involves granting delegated API permissions.
And then call https://graph.microsoft.com/v1.0/me
endpoint to fetch the signed in user details.