docs: function OAuth2Strategy(options, verify) {
    if (typeof options == 'function') {
      verify = options;
      options = undefined;
    }
    options = options || {};
  
    if (!verify) { throw new TypeError('OAuth2Strategy requires a verify callback'); }
    if (!options.authorizationURL) { throw new TypeError('OAuth2Strategy requires a authorizationURL option'); }
    if (!options.tokenURL) { throw new TypeError('OAuth2Strategy requires a tokenURL option'); }
    if (!options.clientID) { throw new TypeError('OAuth2Strategy requires a clientID option'); }
  
    passport.Strategy.call(this);
    this.name = 'oauth2';
    this._verify = verify;
  
    // NOTE: The _oauth2 property is considered "protected".  Subclasses are
    //       allowed to use it when making protected resource requests to retrieve
    //       the user profile.
    this._oauth2 = new OAuth2(options.clientID,  options.clientSecret,
                              '', options.authorizationURL, options.tokenURL, options.customHeaders);
  
    this._callbackURL = options.callbackURL;
    this._scope = options.scope;
    this._scopeSeparator = options.scopeSeparator || ' ';
    this._pkceMethod = (options.pkce === true) ? 'S256' : options.pkce;
    this._key = options.sessionKey || ('oauth2:' + url.parse(options.authorizationURL).hostname);
  
    if (options.store) {
      this._stateStore = options.store;
    } else {
      if (options.state) {
        this._stateStore = options.pkce ? new PKCESessionStateStore({ key: this._key }) : new SessionStateStore({ key: this._key });
      } else {
        if (options.pkce) { throw new TypeError('OAuth2Strategy requires `state: true` option when PKCE is enabled'); }
        this._stateStore = new NullStateStore();
      }
    }
    this._trustProxy = options.proxy;
    this._passReqToCallback = options.passReqToCallback;
    this._skipUserProfile = (options.skipUserProfile === undefined) ? false : options.skipUserProfile;
  }