# Customize security and authentication

## Scope authentication

### Global security

Global security allows users to configure the SDK once and then reuse the security configuration for all subsequent calls.

To use global security, define the security configuration in the `security` block at the root of the SDK:

```yaml
paths:
  /drinks:
    get:
      operationId: listDrinks
      summary: Get a list of drinks.
      description: Get a list of drinks, if authenticated this will include stock levels and product codes otherwise it will only include public information.
      tags:
        - drinks
components:
  securitySchemes:
    api_key:
      type: apiKey
      name: api_key
      in: header
security: # Here
  - api_key: []
```

In the resulting SDK, the user can define the security configuration in the SDK's instantiation. It will then be automatically applied to all subsequent method calls without needing to be passed in as an argument:

<CodeWithTabs client:visible
  tabs={[
    {
      label: "TypeScript",
      language: "typescript",
      code: `import { SDK } from "speakeasy";

  async function run() {
    const sdk = new SDK({
      apiKey: "<YOUR_API_KEY_HERE>",
    });

    const result = await sdk.drinks.listDrinks();

    // Handle the result
    console.log(result);
  }

  run();`,
    },
    {
      label: "Python",
      language: "python",
      code: `import sdk

  s = sdk.SDK(
      api_key="<YOUR_API_KEY_HERE>",
  )

  res = s.drinks.list_drinks()

  if res.drinks is not None:
      # handle response
      pass`,
    },
    {
      label: "Go",
      language: "go",
      code: `package main

  public class Application {

      public static void main(String[] args) {
          try {
              SDK sdk = SDK.builder()
                  .apiKey("<YOUR_API_KEY_HERE>")
                  .build();

              ListDrinksResponse res = sdk.drinks().listDrinks()
                  .call();

              if (res.drinks().isPresent()) {
                  // handle response
              }
          } catch (dev.speakeasyapi.speakeasy.models.errors.SDKError e) {
              // handle exception
          } catch (Exception e) {
              // handle exception
          }
      }
  }`,
    },
    {
      label: "C#",
      language: "csharp",
      code: `using Speakeasy;
  using Speakeasy.Models.Components;

  var sdk = new SDK(
      security: new Security() { ApiKey = "<YOUR_API_KEY_HERE>" }
  );

  try
  {
      var res = await sdk.Drinks.ListDrinksAsync();

      if (res.Drinks != null)
      {
          // handle response
      }
  }
  catch (Exception ex)
  {
    // handle exception
  }`,
    },
    {
      label: "PHP",
      language: "php",
      code: `declare(strict_types=1);

  require 'vendor/autoload.php';

  use OpenAPI\\OpenAPI;

  $sdk = OpenAPI\\SDK::builder()
      ->setSecurity(
          new OpenAPI\\Security(
              apiKey: "<YOUR_API_KEY_HERE>"
          )
      )
      ->build();

  try {
      $response = $sdk->drinks->listDrinks();

      if ($response->drinks !== null) {
          // handle response
      }
  } catch (Exception $e) {
      // handle exception
  }`,
    },
    {
      label: "Ruby",
      language: "ruby",
      code: `require 'openapi'

s = ::OpenApiSDK::SDK.new(security: ::OpenApiSDK::Models::Shared::Security.new(api_key: "<YOUR_API_KEY_HERE>"))

begin
res = s.drinks.list_drinks

      unless res.drinks.nil?
      # handle response
      end

rescue APIError # handle exception
end`,
}
]}
/>

### Per-operation security

<Callout title="Note" type="info">

**Security hoisting:** In cases where global security is **not** defined, Speakeasy automatically hoists the most commonly occurring operation-level security to be considered global. This simplifies SDK usage. To opt out, set `auth.hoistGlobalSecurity: false` in your `gen.yaml`.

</Callout>

Operation-specific security configurations override the default authentication settings for an endpoint. Per-operation configurations are commonly used for operations that do not require authentication or that are part of an authentication flow, such as for obtaining a short-lived access token.

Define `security` within an operation's scope to apply operation-specific security:

```yaml
paths:
  /drinks:
    get:
      operationId: listDrinks
      summary: Get a list of drinks.
      description: Get a list of drinks, if authenticated this will include stock levels and product codes otherwise it will only include public information.
      security: # Here
        - apiKey: []
      tags:
        - drinks
components:
  securitySchemes:
    api_key:
      type: apiKey
      name: api_key
      in: header
security:
  - {}
```

In the resulting SDK, the user can pass in a specific security configuration as an argument to the method call:

<CodeWithTabs client:visible
  tabs={[
    {
      label: "TypeScript",
      language: "typescript",
      code: `import { SDK } from "speakeasy";

  async function run() {
    const sdk = new SDK();

    const operationSecurity = "<YOUR_API_KEY_HERE>";

    const result = await sdk.drinks.listDrinks(operationSecurity);

    // Handle the result
    console.log(result);
  }

  run();`,
    },
    {
      label: "Python",
      language: "python",
      code: `import sdk

  s = sdk.SDK()

  res = s.drinks.list_drinks("<YOUR_API_KEY_HERE>")

  if res.drinks is not None:
      # handle response
      pass`,
    },
    {
      label: "Go",
      language: "go",
      code: `package main

  public class Application {

      public static void main(String[] args) {
          try {
              SDK sdk = SDK.builder()
                  .build();

              ListDrinksResponse res = sdk.drinks().listDrinks()
                  .security(ListDrinksSecurity.builder()
                      .apiKey("<YOUR_API_KEY_HERE>")
                      .build())
                  .call();

              if (res.drinks().isPresent()) {
                  // handle response
              }
          } catch (dev.speakeasyapi.speakeasy.models.errors.SDKError e) {
              // handle exception
          } catch (Exception e) {
              // handle exception
          }
      }
  }`,
    },
    {
      label: "C#",
      language: "csharp",
      code: `using Speakeasy;
  using Speakeasy.Models.Components;

  var sdk = new SDK(
      security: new Security() { ApiKey = "<YOUR_API_KEY_HERE>" }
  );

  try
  {
      var res = await sdk.Drinks.ListDrinksAsync();

      if (res.Drinks != null)
      {
          // handle response
      }
  }
  catch (Exception ex)
  {
    // handle exception
  }`,
    },
    {
      label: "PHP",
      language: "php",
      code: `declare(strict_types=1);

  require 'vendor/autoload.php';

  use OpenAPI\\OpenAPI;

  $sdk = OpenAPI\\SDK::builder()->build();

  $requestSecurity = new ListDrinksSecurity(
      apiKey: '<YOUR_API_KEY_HERE>',
  );

  try {
      $response = $sdk->drinks->listDrinks(
          security: $requestSecurity,
      );

      // handle response

  } catch (Exception $e) {
      // handle exception
  }`,
    },
    {
      label: "Ruby",
      language: "ruby",
      code: `require 'openapi'

    Models = ::OpenApiSDK::Models

    s = ::OpenApiSDK::SDK.new

    begin
      res = s.drinks.list_drinks(
        security: Models::Shared::ListDrinksSecurity.new(
          api_key: '<YOUR_API_KEY_HERE>',
        ),
      )

      unless res.drinks.nil?
        # handle response
      end
    rescue Models::Errors::APIError => e
      # handle exception
      raise e
    end`,
}
]}
/>

## Environment variables

The global parameters and security options for an SDK are commonly set using environment variables. Speakeasy supports this pattern with environment variable prefixes. To enable this feature, set the `envVarPrefix` variable in the language section of the SDK's `gen.yaml` file.

You can then provide global parameters via environment variables in the format `{PREFIX}_{GLOBALNAME}`. The relevant documentation will be automatically included in the README.

Security options can also be set via environment variables if not provided directly to the SDK. For example, a security field like `api_key` can be set with the variable `{PREFIX}_{API_KEY}`:

```ts
const SDK = new SDK({
  apiKey: process.env["SDK_API_KEY"] ?? "",
});
```

<Callout title="Note" type="info">

In some cases, adding `envVarPrefix` may alter the structure of security options. Required global security will become optional to allow you to set it via environment variables.

</Callout>

To learn more about enabling this feature during generation, see the language-specific `gen.yaml` [configuration reference](/docs/speakeasy-reference/generation/gen-yaml).
