Docs: Update developers > plugin > authentication documentation (#63257)

---------

Co-authored-by: Will Browne <wbrowne@users.noreply.github.com>
pull/63704/head
Andres Martinez Gotor 2 years ago committed by GitHub
parent d5b4a1288a
commit d91613448d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 83
      docs/sources/developers/plugins/add-authentication-for-data-source-plugins.md

@ -289,58 +289,71 @@ If your data source uses the same OAuth provider as Grafana itself, for example
To allow Grafana to pass the access token to the plugin, update the data source configuration and set the` jsonData.oauthPassThru` property to `true`. The [DataSourceHttpSettings](https://developers.grafana.com/ui/latest/index.html?path=/story/data-source-datasourcehttpsettings--basic) provides a toggle, the **Forward OAuth Identity** option, for this. You can also build an appropriate toggle to set `jsonData.oauthPassThru` in your data source configuration page UI. To allow Grafana to pass the access token to the plugin, update the data source configuration and set the` jsonData.oauthPassThru` property to `true`. The [DataSourceHttpSettings](https://developers.grafana.com/ui/latest/index.html?path=/story/data-source-datasourcehttpsettings--basic) provides a toggle, the **Forward OAuth Identity** option, for this. You can also build an appropriate toggle to set `jsonData.oauthPassThru` in your data source configuration page UI.
When configured, Grafana will pass the user's token to the plugin in an Authorization header, available on the `QueryDataRequest` object on the `QueryData` request in your backend data source. When configured, Grafana can forward authorization HTTP headers such as `Authorization` or `X-ID-Token` to a backend data source. This information is available across the `QueryData`, `CallResource` and `CheckHealth` requests.
To get Grafana to forward the headers, create a HTTP client using the [Grafana Plugin SDK](https://pkg.go.dev/github.com/grafana/grafana-plugin-sdk-go/backend/httpclient). This package exposes request information which can be subsequently forwarded downstream and/or used directly within the plugin.
```go ```go
func (ds *dataSource) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) { func NewDatasource(settings backend.DataSourceInstanceSettings) (instancemgmt.Instance, error) {
token := strings.Fields(req.GetHTTPHeader(backend.OAuthIdentityTokenHeaderName)) opts, err := settings.HTTPClientOptions()
var ( if err != nil {
tokenType = token[0] return nil, fmt.Errorf("http client options: %w", err)
accessToken = token[1] }
) // Important to reuse the same client for each query, to avoid using all available connections on a host
cl, err := httpclient.New(opts)
// ... if err != nil {
return &backend.CheckHealthResult{Status: backend.HealthStatusOk}, nil return nil, fmt.Errorf("httpclient new: %w", err)
}
return &Datasource{
httpClient: cl,
}, nil
} }
func (ds *dataSource) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { func (ds *dataSource) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
token := strings.Fields(req.GetHTTPHeader(backend.OAuthIdentityTokenHeaderName)) // Important to keep the Context, since the injected middleware is configured there
var ( req, err := http.NewRequestWithContext(ctx, http.MethodGet, "https://some-url", nil)
tokenType = token[0] if err != nil {
accessToken = token[1] return nil, fmt.Errorf("new request with context: %w", err)
) }
// Authorization header will be automatically injected if oauthPassThru is configured
for _, q := range req.Queries { resp, err := ds.httpClient.Do(req)
// ... // ...
}
} }
``` ```
In addition, if the user's token includes an ID token, Grafana will pass the user's ID token to the plugin in an `X-ID-Token` header, available on the `QueryDataRequest` object on the `QueryData` request in your backend data source. You can see a full working example here: [datasource-http-backend](https://github.com/grafana/grafana-plugin-examples/tree/main/examples/datasource-http-backend).
If you need to access HTTP header information directory, you can also extract that information from the request:
```go ```go
func (ds *dataSource) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) { func (ds *dataSource) CheckHealth(ctx context.Context, req *backend.CheckHealthRequest) (*backend.CheckHealthResult, error) {
idToken := req.GetHTTPHeader(backend.OAuthIdentityIDTokenHeaderName) token := strings.Fields(req.GetHTTPHeader(backend.OAuthIdentityTokenHeaderName))
var (
tokenType = token[0]
accessToken = token[1]
)
idToken := req.GetHTTPHeader(backend.OAuthIdentityIDTokenHeaderName) // present if user's token includes an ID token
// ... // ...
return &backend.CheckHealthResult{Status: backend.HealthStatusOk}, nil return &backend.CheckHealthResult{Status: backend.HealthStatusOk}, nil
} }
func (ds *dataSource) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { func (ds *dataSource) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
token := strings.Fields(req.GetHTTPHeader(backend.OAuthIdentityTokenHeaderName))
var (
tokenType = token[0]
accessToken = token[1]
)
idToken := req.GetHTTPHeader(backend.OAuthIdentityIDTokenHeaderName) idToken := req.GetHTTPHeader(backend.OAuthIdentityIDTokenHeaderName)
for _, q := range req.Queries { for _, q := range req.Queries {
// ... // ...
} }
} }
```
The `Authorization` and `X-ID-Token` headers will also be available on the `CallResourceRequest` object on the `CallResource` request in your backend data source when `jsonData.oauthPassThru` is `true`.
```go
func (ds *dataSource) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error { func (ds *dataSource) CallResource(ctx context.Context, req *backend.CallResourceRequest, sender backend.CallResourceResponseSender) error {
token := req.GetHTTPHeader(backend.OAuthIdentityTokenHeaderName) token := req.GetHTTPHeader(backend.OAuthIdentityTokenHeaderName)
idToken := req.GetHTTPHeader(backend.OAuthIdentityIDTokenHeaderName) // present if user's token includes an ID token idToken := req.GetHTTPHeader(backend.OAuthIdentityIDTokenHeaderName)
// ... // ...
} }
@ -348,9 +361,11 @@ func (ds *dataSource) CallResource(ctx context.Context, req *backend.CallResourc
## Forward cookies for the logged-in user ## Forward cookies for the logged-in user
Your data source plugin can forward certain cookies for the logged-in Grafana user to the data source. Use the [DataSourceHttpSettings](https://developers.grafana.com/ui/latest/index.html?path=/story/data-source-datasourcehttpsettings--basic) component on the data source's configuration page. It provides the **Allowed cookies** option, where the names of cookies to pass to the plugin can be specified. Your data source plugin can forward cookies for the logged-in Grafana user to the data source. Use the [DataSourceHttpSettings](https://developers.grafana.com/ui/latest/index.html?path=/story/data-source-datasourcehttpsettings--basic) component on the data source's configuration page. It provides the **Allowed cookies** option, where you can specify the cookie names.
When configured, as with [authorization headers](#forward-oauth-identity-for-the-logged-in-user), these cookies are automatically injected if the SDK HTTP client is used.
When configured, Grafana will pass these cookies to the plugin in the `Cookie` header, available in the `QueryData`, `CallResource` and `CheckHealth` requests in your backend data source. You can also extract the cookies in the `QueryData`, `CallResource` and `CheckHealth` requests if required.
```go ```go
func (ds *dataSource) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { func (ds *dataSource) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {
@ -374,7 +389,7 @@ func (ds *dataSource) CheckHealth(ctx context.Context, req *backend.CheckHealthR
## Forward user header for the logged-in user ## Forward user header for the logged-in user
When [send_user_header]({{< relref "../../setup-grafana/configure-grafana/_index.md#send_user_header" >}}) is enabled, Grafana will pass the user header to the plugin in the `X-Grafana-User` header, available in the `QueryData`, `CallResource` and `CheckHealth` requests in your backend data source. When [send_user_header]({{< relref "../../setup-grafana/configure-grafana/_index.md#send_user_header" >}}) is enabled, Grafana will pass the user header to the plugin using the `X-Grafana-User` header. You can forward this header as well as [authorization headers](#forward-oauth-identity-for-the-logged-in-user) or [configured cookies](#forward-cookies-for-the-logged-in-user).
```go ```go
func (ds *dataSource) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) { func (ds *dataSource) QueryData(ctx context.Context, req *backend.QueryDataRequest) (*backend.QueryDataResponse, error) {

Loading…
Cancel
Save