You are here

Authentication.php in Auth0 Single Sign On 8.2

Namespace

Auth0\SDK\API

File

vendor/auth0/auth0-php/src/API/Authentication.php
View source
<?php

/**
 * Authentication API wrapper
 *
 * @package Auth0\SDK\API
 *
 * @see https://auth0.com/docs/api/authentication
 */
namespace Auth0\SDK\API;

use Auth0\SDK\API\Header\Authorization\AuthorizationBearer;
use Auth0\SDK\API\Header\ContentType;
use Auth0\SDK\API\Header\ForwardedFor;
use Auth0\SDK\API\Helpers\ApiClient;
use Auth0\SDK\Exception\ApiException;
use Auth0\SDK\API\Helpers\InformationHeaders;
use GuzzleHttp\Psr7;

/**
 * Class Authentication
 *
 * @package Auth0\SDK\API
 */
class Authentication {

  /**
   * Domain for the Auth0 Tenant.
   *
   * @var string
   */
  private $domain;

  /**
   * Client ID for the Auth0 Application.
   *
   * @var null|string
   */
  private $client_id;

  /**
   * Client Secret for the Auth0 Application.
   *
   * @var null|string
   */
  private $client_secret;

  /**
   * API audience identifier for the access token.
   *
   * @var null|string
   */
  private $audience;

  /**
   * Scopes to request during login.
   *
   * @var null|string
   */
  private $scope;

  /**
   * Options for the Guzzle HTTP client.
   *
   * @var array
   */
  private $guzzleOptions;

  /**
   * ApiClient instance.
   *
   * @var ApiClient
   */
  private $apiClient;

  /**
   * Authentication constructor.
   *
   * @param string      $domain        Tenant domain, found in Application settings.
   * @param null|string $client_id     Client ID, found in Application settings.
   * @param null|string $client_secret Client Secret, found in Application settings.
   * @param null|string $audience      API audience identifier for the access token, found in API settings.
   * @param null|string $scope         Scopes to request during login.
   * @param array       $guzzleOptions Options for the Guzzle HTTP client.
   *
   * @link https://auth0.com/docs/scopes/current
   * @link http://docs.guzzlephp.org/en/stable/request-options.html
   */
  public function __construct($domain, $client_id = null, $client_secret = null, $audience = null, $scope = null, $guzzleOptions = []) {
    $this->domain = $domain;
    $this->client_id = $client_id;
    $this->client_secret = $client_secret;
    $this->audience = $audience;
    $this->scope = $scope;
    $this->guzzleOptions = $guzzleOptions;
    $this->apiClient = new ApiClient([
      'domain' => 'https://' . $this->domain,
      'basePath' => '/',
      'guzzleOptions' => $guzzleOptions,
    ]);
  }

  /**
   * Builds and returns the authorization URL.
   *
   * @param string      $response_type     Response type requested, typically "code" for web application login.
   * @param string      $redirect_uri      Redirect URI for login and consent, must be white-listed.
   * @param null|string $connection        Connection parameter to send with the request.
   * @param null|string $state             State parameter to send with the request.
   * @param array       $additional_params Additional URL parameters to send with the request.
   *
   * @return string
   *
   * @link https://auth0.com/docs/api/authentication#authorize-application
   */
  public function get_authorize_link($response_type, $redirect_uri, $connection = null, $state = null, array $additional_params = []) {
    $additional_params['response_type'] = $response_type;
    $additional_params['redirect_uri'] = $redirect_uri;
    $additional_params['client_id'] = $this->client_id;
    if ($connection !== null) {
      $additional_params['connection'] = $connection;
    }
    if ($state !== null) {
      $additional_params['state'] = $state;
    }
    return sprintf('https://%s/authorize?%s', $this->domain, Psr7\build_query($additional_params));
  }

  /**
   * Build and return a SAMLP link.
   *
   * @param null|string $client_id  Client ID to use, null to use the value set during class initialization.
   * @param string      $connection Connection parameter to add.
   *
   * @return string
   *
   * @link https://auth0.com/docs/connections/enterprise/samlp
   */
  public function get_samlp_link($client_id = null, $connection = '') {
    return sprintf('https://%s/samlp/%s?connection=%s', $this->domain, empty($client_id) ? $this->client_id : $client_id, $connection);
  }

  /**
   * Build and return a SAMLP metadata link.
   *
   * @param null|string $client_id Client ID to use, null to use the value set during class initialization.
   *
   * @return string
   *
   * @link https://auth0.com/docs/connections/enterprise/samlp
   */
  public function get_samlp_metadata_link($client_id = null) {
    return sprintf('https://%s/samlp/metadata/%s', $this->domain, empty($client_id) ? $this->client_id : $client_id);
  }

  /**
   * Build and return a WS-Federation link
   *
   * @param null|string $client_id Client ID to use, null to use the value set during class initialization.
   * @param array       $params    Request parameters for the WS-Fed request.
   *      - params.client-id The client-id of your application.
   *      - params.wtrealm   Can be used in place of client-id.
   *      - params.whr       The name of the connection (used to skip the login page).
   *      - params.wctx      Your application's state.
   *      - params.wreply    The callback URL.
   *
   * @return string
   *
   * @link https://auth0.com/docs/protocols/ws-fed
   */
  public function get_wsfed_link($client_id = null, array $params = []) {
    return sprintf('https://%s/wsfed/%s?%s', $this->domain, empty($client_id) ? $this->client_id : $client_id, Psr7\build_query($params));
  }

  /**
   * Build and return a WS-Federation metadata link
   *
   * @return string
   *
   * @link https://auth0.com/docs/protocols/ws-fed
   */
  public function get_wsfed_metadata_link() {
    return 'https://' . $this->domain . '/wsfed/FederationMetadata/2007-06/FederationMetadata.xml';
  }

  /**
   * Builds and returns a logout URL to terminate an SSO session.
   *
   * @param null|string $returnTo  URL to return to after logging in; must be white-listed in Auth0.
   * @param null|string $client_id Client ID to use Application-specific returnTo URLs.
   * @param boolean     $federated Attempt a federated logout.
   *
   * @return string
   *
   * @link https://auth0.com/docs/api/authentication#logout
   */
  public function get_logout_link($returnTo = null, $client_id = null, $federated = false) {
    $params = [];
    if ($returnTo !== null) {
      $params['returnTo'] = $returnTo;
    }
    if ($client_id !== null) {
      $params['client_id'] = $client_id;
    }
    if ($federated) {
      $params['federated'] = '';
    }
    return sprintf('https://%s/v2/logout?%s', $this->domain, Psr7\build_query($params));
  }

  /**
   * Start passwordless login process for email
   *
   * @param string $email      Email address to use.
   * @param string $type       Use null or "link" to send a link, use "code" to send a verification code.
   * @param array  $authParams Link parameters (like scope, redirect_uri, protocol, response_type) to modify.
   *
   * @return mixed
   *
   * @link https://auth0.com/docs/api/authentication#get-code-or-link
   */
  public function email_passwordless_start($email, $type, array $authParams = []) {
    $data = [
      'client_id' => $this->client_id,
      'connection' => 'email',
      'send' => $type,
      'email' => $email,
    ];
    if (!empty($authParams)) {
      $data['authParams'] = $authParams;
    }
    return $this->apiClient
      ->method('post')
      ->addPath('passwordless')
      ->addPath('start')
      ->withBody(json_encode($data))
      ->call();
  }

  /**
   * Start passwordless login process for SMS.
   *
   * @param string $phone_number Phone number to use.
   *
   * @return mixed
   *
   * @link https://auth0.com/docs/api/authentication#get-code-or-link
   */
  public function sms_passwordless_start($phone_number) {
    $data = [
      'client_id' => $this->client_id,
      'connection' => 'sms',
      'phone_number' => $phone_number,
    ];
    return $this->apiClient
      ->method('post')
      ->addPath('passwordless')
      ->addPath('start')
      ->withBody(json_encode($data))
      ->call();
  }

  /**
   * Make an authenticated request to the /userinfo endpoint.
   *
   * @param string $access_token Bearer token to use for the request.
   *
   * @return mixed
   *
   * @link https://auth0.com/docs/api/authentication#user-profile
   */
  public function userinfo($access_token) {
    return $this->apiClient
      ->method('get')
      ->addPath('userinfo')
      ->withHeader(new AuthorizationBearer($access_token))
      ->call();
  }

  /**
   * Makes a call to the `oauth/token` endpoint.
   *
   * @param array $options Options for the token endpoint request.
   *      - options.grant_type    Grant type to use; required.
   *      - options.client_id     Application Client ID; required.
   *      - options.client_secret Application Client Secret; required if token endpoint requires authentication.
   *      - options.scope         Access token scope requested.
   *      - options.audience      API audience identifier for access token.
   *
   * @return mixed
   *
   * @throws ApiException If grant_type is missing from $options.
   */
  public function oauth_token(array $options = []) {
    if (!isset($options['client_id'])) {
      $options['client_id'] = $this->client_id;
    }
    if (!isset($options['client_secret'])) {
      $options['client_secret'] = $this->client_secret;
    }
    if (!isset($options['grant_type'])) {
      throw new ApiException('grant_type is mandatory');
    }
    $request = $this->apiClient
      ->method('post')
      ->addPath('oauth/token')
      ->withBody(json_encode($options));
    if (isset($options['auth0_forwarded_for'])) {
      $request
        ->withHeader(new ForwardedFor($options['auth0_forwarded_for']));
    }
    return $request
      ->call();
  }

  /**
   * Makes a call to the `oauth/token` endpoint with `authorization_code` grant type
   *
   * @param string $code         Authorization code received during login.
   * @param string $redirect_uri Redirect URI sent with authorize request.
   *
   * @return mixed
   *
   * @throws ApiException If grant_type is missing.
   */
  public function code_exchange($code, $redirect_uri) {
    $options = [];
    $options['client_secret'] = $this->client_secret;
    $options['redirect_uri'] = $redirect_uri;
    $options['code'] = $code;
    $options['grant_type'] = 'authorization_code';
    return $this
      ->oauth_token($options);
  }

  /**
   * Makes a call to the `oauth/token` endpoint with `password-realm` grant type.
   *
   * @param array       $options    Options for this grant.
   *      - options.username Username or email of the user logging in; required.
   *      - options.password Password of the user logging in; required.
   *      - options.realm    Database realm to use; required.
   *      - options.scope    Access token scope requested.
   *      - options.audience API audience identifier for access token.
   * @param string|null $ip_address Pass in an IP address to set an Auth0-Forwarded-For header.
   *
   * @return mixed
   *
   * @throws ApiException If username, password, or realm are missing from $options.
   */
  public function login(array $options, $ip_address = null) {
    if (!isset($options['username'])) {
      throw new ApiException('username is mandatory');
    }
    if (!isset($options['password'])) {
      throw new ApiException('password is mandatory');
    }
    if (!isset($options['realm'])) {
      throw new ApiException('realm is mandatory');
    }
    if (!empty($ip_address)) {
      $options['auth0_forwarded_for'] = $ip_address;
    }
    $options['grant_type'] = 'http://auth0.com/oauth/grant-type/password-realm';
    return $this
      ->oauth_token($options);
  }

  /**
   * Makes a call to the `oauth/token` endpoint with `password` grant type
   *
   * @param array       $options    Options for this grant.
   *      - options.username Username or email of the user logging in; required.
   *      - options.password Password of the user logging in; required.
   *      - options.scope    Access token scope requested.
   *      - options.audience API audience identifier for access token.
   * @param string|null $ip_address Pass in an IP address to set an Auth0-Forwarded-For header.
   *
   * @return mixed
   *
   * @throws ApiException If username or password is missing.
   *
   * @link https://auth0.com/docs/api-auth/grant/password
   */
  public function login_with_default_directory(array $options, $ip_address = null) {
    if (!isset($options['username'])) {
      throw new ApiException('username is mandatory');
    }
    if (!isset($options['password'])) {
      throw new ApiException('password is mandatory');
    }
    if (!empty($ip_address)) {
      $options['auth0_forwarded_for'] = $ip_address;
    }
    $options['grant_type'] = 'password';
    return $this
      ->oauth_token($options);
  }

  /**
   * Makes a call to the `oauth/token` endpoint with `client_credentials` grant type.
   *
   * TODO: MAJOR - Add a new ApiException for missing audience.
   *
   * @param array $options Information required for this grant.
   *      - options.client_id     Application Client ID.
   *      - options.client_secret Application Client Secret.
   *      - options.audience      API Audience requested.
   *
   * @return mixed
   *
   * @throws ApiException If client_id or client_secret are missing.
   *
   * @link https://auth0.com/docs/api-auth/grant/client-credentials
   */
  public function client_credentials(array $options) {
    if (!isset($options['client_secret'])) {
      $options['client_secret'] = $this->client_secret;
    }
    if (empty($options['client_secret'])) {
      throw new ApiException('client_secret is mandatory');
    }
    if (!isset($options['client_id'])) {
      $options['client_id'] = $this->client_id;
    }
    if (empty($options['client_id'])) {
      throw new ApiException('client_id is mandatory');
    }
    if (!isset($options['audience'])) {
      $options['audience'] = $this->audience;
    }
    $options['grant_type'] = 'client_credentials';
    return $this
      ->oauth_token($options);
  }

  /**
   * Use a refresh token grant to get new tokens.
   *
   * @param string $refresh_token Refresh token to use.
   * @param array  $options       Array of options to override defaults.
   *
   * @return mixed
   *
   * @throws ApiException If $refresh_token, client_secret, or client_id is blank.
   *
   * @link https://auth0.com/docs/api/authentication#refresh-token
   */
  public function refresh_token($refresh_token, array $options = []) {
    if (empty($refresh_token)) {
      throw new ApiException('Refresh token cannot be blank');
    }
    if (!isset($options['client_secret'])) {
      $options['client_secret'] = $this->client_secret;
    }
    if (empty($options['client_secret'])) {
      throw new ApiException('client_secret is mandatory');
    }
    if (!isset($options['client_id'])) {
      $options['client_id'] = $this->client_id;
    }
    if (empty($options['client_id'])) {
      throw new ApiException('client_id is mandatory');
    }
    $options['refresh_token'] = $refresh_token;
    $options['grant_type'] = 'refresh_token';
    return $this
      ->oauth_token($options);
  }

  /**
   * Create a new user using active authentication.
   * This endpoint only works for database connections.
   *
   * @param string $email      Email for the user signing up.
   * @param string $password   New password for the user signing up.
   * @param string $connection Database connection to create the user in.
   *
   * @return mixed
   *
   * @link https://auth0.com/docs/api/authentication#signup
   */
  public function dbconnections_signup($email, $password, $connection) {
    $data = [
      'client_id' => $this->client_id,
      'email' => $email,
      'password' => $password,
      'connection' => $connection,
    ];
    return $this->apiClient
      ->method('post')
      ->addPath('dbconnections')
      ->addPath('signup')
      ->withBody(json_encode($data))
      ->call();
  }

  /**
   * Send a change password email.
   * This endpoint only works for database connections.
   *
   * @param string      $email      Email for the user changing their password.
   * @param string      $connection The name of the database connection this user is in.
   * @param null|string $password   New password to use.
   *      If this parameter is provided, when the user clicks on the confirm password change link,
   *      this value will be set for the user.
   *      If this parameter is NOT provided, the user will be asked for a new password.
   *
   * @return mixed
   *
   * @link https://auth0.com/docs/api/authentication#change-password
   */
  public function dbconnections_change_password($email, $connection, $password = null) {
    $data = [
      'client_id' => $this->client_id,
      'email' => $email,
      'connection' => $connection,
    ];
    if ($password !== null) {
      $data['password'] = $password;
    }
    return $this->apiClient
      ->method('post')
      ->addPath('dbconnections')
      ->addPath('change_password')
      ->withBody(json_encode($data))
      ->call();
  }

  /*
   * Deprecated
   */

  // phpcs:disable

  /**
   * Set an ApiClient for use in this object
   *
   * @deprecated 5.4.0, not used and no replacement provided.
   *
   * @return void
   *
   * @codeCoverageIgnore - Deprecated
   */
  protected function setApiClient() {
    $apiDomain = "https://{$this->domain}";
    $client = new ApiClient([
      'domain' => $apiDomain,
      'basePath' => '/',
      'guzzleOptions' => $this->guzzleOptions,
    ]);
    $this->apiClient = $client;
  }

  /**
   * Verify SMS code
   *
   * @deprecated 5.4.0, legacy authentication pipeline, no alternative provided.
   *
   * @param string $phone_number
   * @param string $code
   * @param string $scope
   *
   * @return mixed
   *
   * @throws ApiException
   *
   * @codeCoverageIgnore - Deprecated
   */
  public function sms_code_passwordless_verify($phone_number, $code, $scope = 'openid') {
    return $this
      ->authorize_with_ro($phone_number, $code, $scope, 'sms');
  }

  /**
   * Verify email code
   *
   * @deprecated 5.4.0, legacy authentication pipeline, no alternative provided.
   *
   * @param string $email
   * @param string $code
   * @param string $scope
   *
   * @return mixed
   *
   * @throws ApiException
   *
   * @codeCoverageIgnore - Deprecated
   */
  public function email_code_passwordless_verify($email, $code, $scope = 'openid') {
    return $this
      ->authorize_with_ro($email, $code, $scope, 'email');
  }

  /**
   * Obtain an impersonation URL to login as another user.
   * Impersonation functionality may be disabled by default for your tenant.
   *
   * @deprecated 5.4.0, legacy authentication pipeline, no alternative provided.
   *
   * @param string $access_token
   * @param string $user_id
   * @param string $protocol
   * @param string $impersonator_id
   * @param string $client_id
   * @param array  $additionalParameters
   *
   * @return mixed
   *
   * @see https://auth0.com/docs/api/authentication#impersonation
   *
   * @codeCoverageIgnore - Deprecated
   */
  public function impersonate($access_token, $user_id, $protocol, $impersonator_id, $client_id, array $additionalParameters = []) {
    $data = [
      'protocol' => $protocol,
      'impersonator_id' => $impersonator_id,
      'client_id' => $client_id,
      'additionalParameters' => $additionalParameters,
    ];
    return $this->apiClient
      ->method('post')
      ->addPath('users', $user_id)
      ->addPath('impersonate')
      ->withHeader(new AuthorizationBearer($access_token))
      ->withBody(json_encode($data))
      ->call();
  }

  /**
   * Authorize using an access token
   *
   * @deprecated 5.1.1, disabled by default for new tenants as of 8 June
   * 2017. Open the browser to do social authentication instead, which is
   * what Google and Facebook are recommending.
   *
   * @param string $access_token
   * @param string $connection
   * @param string $scope
   * @param array  $additional_params
   *
   * @return mixed
   *
   * @see https://auth0.com/docs/api/authentication#social-with-provider-s-access-token
   * @see https://developers.googleblog.com/2016/08/modernizing-oauth-interactions-in-native-apps.html
   * @see https://auth0.com/docs/api-auth/intro
   *
   * @codeCoverageIgnore - Deprecated
   */
  public function authorize_with_accesstoken($access_token, $connection, $scope = 'openid', array $additional_params = []) {
    $data = array_merge($additional_params, [
      'client_id' => $this->client_id,
      'access_token' => $access_token,
      'connection' => $connection,
      'scope' => $scope,
    ]);
    return $this->apiClient
      ->method('post')
      ->addPath('oauth')
      ->addPath('access_token')
      ->withBody(json_encode($data))
      ->call();
  }

  /**
   * DEPRECATED - This endpoint is part of the legacy authentication pipeline and
   * has been replaced in favor of the Password Grant. For more information on the
   * latest authentication pipeline refer to Introducing OIDC Conformant
   * Authentication.
   *
   * @deprecated 5.0.0, use `login` instead. Use only for passwordless verify
   *
   * @param string      $username
   * @param string      $password
   * @param string      $scope
   * @param null|string $connection
   * @param null|string $id_token
   * @param null|string $device
   *
   * @return mixed
   *
   * @throws ApiException
   *
   * @see https://auth0.com/docs/api/authentication#resource-owner
   * @see https://auth0.com/docs/api-auth/intro
   *
   * @codeCoverageIgnore - Deprecated
   */
  public function authorize_with_ro($username, $password, $scope = 'openid', $connection = null, $id_token = null, $device = null) {
    $data = [
      'client_id' => $this->client_id,
      'username' => $username,
      'password' => $password,
      'scope' => $scope,
    ];
    if ($device !== null) {
      $data['device'] = $device;
    }
    if ($id_token !== null) {
      $data['id_token'] = $id_token;
      $data['grant_type'] = 'urn:ietf:params:oauth:grant-type:jwt-bearer';
    }
    else {
      if ($connection === null) {
        throw new ApiException('You need to specify a connection for grant_type=password authentication');
      }
      $data['grant_type'] = 'password';
      $data['connection'] = $connection;
    }
    return $this->apiClient
      ->method('post')
      ->addPath('oauth')
      ->addPath('ro')
      ->withBody(json_encode($data))
      ->call();
  }

}

Classes

Namesort descending Description
Authentication Class Authentication