---
# System prepended metadata

title: GoogleのOAuthFactoryについて
tags: [quartetcom]

---

---
tags: quartetcom
---
# GoogleのOAuthFactoryについて

もとはこうなってる

```php
class OAuthFactory
{
    private const SCOPE_ADWORDS = 'https://www.googleapis.com/auth/adwords';
    private const SCOPE_EMAIL = 'email';
    private const SCOPE_TRANSLATE = 'https://www.googleapis.com/auth/cloud-translation';
    private const AUTH_URL = 'https://accounts.google.com/o/oauth2/v2/auth';

    public function __construct(
        private readonly string $clientId,
        private readonly string $clientSecret,
        private readonly DevUserChecker $devUserChecker,
    ) {
    }

    public function create(UserInterface $user, string $callbackUrl): OAuth2
    {
        $oauth = new OAuth2([
            'clientId' => $this->clientId,
            'clientSecret' => $this->clientSecret,
        ]);
        $oauth->setRedirectUri($callbackUrl);
        $oauth->setTokenCredentialUri(CredentialsLoader::TOKEN_CREDENTIAL_URI);
        $oauth->setAuthorizationUri(self::AUTH_URL);
        $oauth->setScope(implode(' ', $this->getScopes($user)));
        $oauth->setState(md5('talaria'.microtime(true)));

        return $oauth;
    }

    private function getScopes(UserInterface $user): array
    {
        $scopes = [self::SCOPE_ADWORDS, self::SCOPE_EMAIL];
        if ($this->devUserChecker->isDevUser($user)) {
            $scopes[] = self::SCOPE_TRANSLATE;
        }

        return $scopes;
    }
}
```

## DevCheckerを使ってやりたいこと

ユーザが開発者？だったら、スコープを追加する。
= スコープが決まればOK


## こうするとよいんじゃないか

```plantuml
class OAuthFactory {
    - $scopesResolver: ScopesResolver
    + getScopes()
}

class ScopesResolver {
    - $scopes: ScopesInterface[]
    + resolve(): ScopesInterface
}
interface ScopesInterface {
    + getScopes(): string[]
    + supports(): bool
}

class DefaultScopes {
    
}

OAuthFactory o- ScopesResolver
ScopesResolver *-- ScopesInterface
ScopesInterface <.. DefaultScopes
ScopesInterface <.. DeveloperScopes
note bottom: カスタマイズしたクラス

```

OAuthFactoryはResolverを持っていて、
そのResolverを使って取得したScopeInterfaceから
該当するスコープを手に入れる。

Talariaでは、たとえば`DeveloperScopes`というクラスを作って、DevUserChecker::isDevUser()部分の実装をすればよいと思われ。

```php

public function supports(): bool
{
    $user = $this->security->getUser();
    assert($user instanceof User);
    return in_array($user->getUserName(), $this->devUserEmails);
}
```

