public function authenticate($code)
    {
        // Validate code
        if (!$code || strlen($code) != 6) {
            throw new Exception('Invalid authorization code');
        }

        // Check for required items
        if (!$this->clientId) {
            throw new Exception('Client ID is required');
        }
        if (!$this->clientSecret) {
            throw new Exception('Client secret is required');
        }
        if (!$this->redirectUri) {
            throw new Exception('Redirect URI is required');
        }

        $fields = [
            'client_id'     => $this->clientId,
            'client_secret' => $this->clientSecret,
            'code'          => $code,
            'redirect_uri'  => urlencode($this->redirectUri),
            'grant_type'    => 'authorization_code'
        ];

        $url  = 'https://';
        $url .= $this->level . '.';
        $url .= (!empty($this->environment)) ? $this->environment . '.' : '';
        $url .= self::HOSTNAME . '/' . self::TOKEN;

        $this->http->setUrl($url)
                   ->setPostFields($fields)
                   ->setHeader(['Accept' => 'application/json']);

        $data = json_decode($this->http->execute());

        if (isset($data->access_token)) {
            $this->setAccessToken($data->access_token);
            $this->setOrcid($data->orcid);
        } else {
            // Seems like the response format changes on occasion...not sure what's going on there?
            $error = (isset($data->error_description)) ? $data->error_description : $data->{'error-desc'}->value;

            throw new Exception($error);
        }

        return $this;
    }