├── CONTRIBUTING.md ├── LICENSE.md ├── composer.json └── src ├── ApiKey.php ├── Authc ├── Api │ ├── ApiAuthenticationResult.php │ ├── ApiKeyEncryptionOptions.php │ ├── ApiKeyEncryptionUtils.php │ ├── ApiRequestAuthenticator.php │ ├── AuthenticatorResult.php │ ├── BasicAuthenticationResult.php │ ├── BasicRequestAuthenticator.php │ ├── InternalRequestAuthenticator.php │ ├── OAuthAuthenticationResult.php │ ├── OAuthBearerAuthenticationResult.php │ ├── OAuthBearerRequestAuthenticator.php │ ├── OAuthClientCredentialsAuthenticationResult.php │ ├── OAuthClientCredentialsRequestAuthenticator.php │ ├── OAuthRequestAuthenticator.php │ ├── Request.php │ └── RequestAuthenticator.php ├── AuthenticationRequest.php ├── BasicAuthenticator.php └── UsernamePasswordRequest.php ├── Cache ├── ArrayCacheManager.php ├── Cache.php ├── CacheItemWrapper.php ├── CacheManager.php ├── CachePSR6Adapter.php ├── Cacheable.php ├── MemcachedCacheManager.php ├── NullCacheManager.php ├── PSR6CacheKeyTrait.php ├── PSR6CacheManagerInterface.php ├── PSR6InstanceCacheManager.php ├── RedisCacheManager.php └── Tags │ └── CacheTagExtractor.php ├── Client.php ├── ClientBuilder.php ├── DataStore ├── ClassNameResolver.php ├── DataStore.php ├── DefaultClassNameResolver.php ├── DefaultDataStore.php ├── DefaultResourceFactory.php ├── InternalDataStore.php └── ResourceFactory.php ├── Directory ├── PasswordPolicy.php └── PasswordStrength.php ├── Exceptions ├── Cache │ ├── InvalidCacheManagerException.php │ └── InvalidLegacyCacheManagerException.php ├── IdSite │ ├── InvalidCallbackUriException.php │ └── JWTUsedAlreadyException.php └── RequestAuthenticatorException.php ├── Http └── Authc │ ├── BasicRequestSigner.php │ ├── RequestSigner.php │ ├── SAuthc1Authentication.php │ ├── SAuthc1RequestSigner.php │ └── StormpathBasicAuthentication.php ├── Mail ├── EmailTemplate.php ├── ModeledEmailTemplate.php ├── ModeledEmailTemplateList.php ├── UnmodeledEmailTemplate.php └── UnmodeledEmailTemplateList.php ├── Mfa ├── Challenge.php ├── ChallengeList.php ├── Factor.php ├── FactorList.php ├── GoogleAuthenticatorChallenge.php ├── GoogleAuthenticatorFactor.php ├── Phone.php ├── PhoneList.php ├── SmsChallenge.php └── SmsFactor.php ├── Oauth ├── ExchangeIdSiteTokenAttempt.php ├── ExchangeIdSiteTokenAuthenticator.php ├── ExchangeIdSiteTokenRequest.php ├── OauthGrantAuthenticationResult.php ├── OauthGrantAuthenticationResultBuilder.php ├── PasswordGrantAuthenticationAttempt.php ├── PasswordGrantAuthenticator.php ├── PasswordGrantRequest.php ├── RefreshGrantAuthenticationAttempt.php ├── RefreshGrantAuthenticator.php ├── RefreshGrantRequest.php └── VerifyAccessToken.php ├── Provider ├── FacebookProviderAccountRequest.php ├── GithubProviderAccountRequest.php ├── GoogleProviderAccountRequest.php ├── LinkedInProviderAccountRequest.php ├── ProviderAccountRequest.php └── ProviderDataClassNameResolver.php ├── Resource ├── AbstractCollectionResource.php ├── AccessToken.php ├── AccessTokenList.php ├── Account.php ├── AccountCreationPolicy.php ├── AccountList.php ├── AccountStore.php ├── AccountStoreMapping.php ├── AccountStoreMappingList.php ├── ApiKey.php ├── ApiKeyList.php ├── Application.php ├── ApplicationList.php ├── AssertionConsumerServicePostEndpoint.php ├── AuthenticationResult.php ├── BasicLoginAttempt.php ├── CustomData.php ├── Deletable.php ├── Directory.php ├── DirectoryList.php ├── EmailVerificationToken.php ├── Error.php ├── Expansion.php ├── FacebookProvider.php ├── FacebookProviderData.php ├── GithubProvider.php ├── GithubProviderData.php ├── GoogleProvider.php ├── GoogleProviderData.php ├── GrantAuthenticationToken.php ├── Group.php ├── GroupList.php ├── GroupMembership.php ├── GroupMembershipList.php ├── InstanceResource.php ├── LinkedInProvider.php ├── LinkedInProviderData.php ├── OauthPolicy.php ├── Order.php ├── Organization.php ├── OrganizationList.php ├── Page.php ├── PaginatedIterator.php ├── PasswordResetToken.php ├── Provider.php ├── ProviderAccountAccess.php ├── ProviderAccountResult.php ├── ProviderData.php ├── RefreshToken.php ├── RefreshTokenList.php ├── Resource.php ├── ResourceError.php ├── SamlProvider.php ├── SamlProviderData.php ├── Saveable.php ├── Search.php ├── Tenant.php ├── VerificationEmail.php └── X509SigningCert.php ├── Saml ├── AttributeStatementMappingRule.php ├── AttributeStatementMappingRuleBuilder.php ├── AttributeStatementMappingRules.php └── AttributeStatementMappingRulesBuilder.php ├── Stormpath.php └── Util ├── Magic.php ├── NonceStore.php ├── RequestUtils.php ├── UUID.php ├── UserAgentBuilder.php └── Version.php /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Contributions, bug reports and issues are very welcome. Stormpath regularly maintains this repository, and are quick to review pull requests and accept changes! 4 | 5 | You can make your own contributions by forking the `dev` branch of this repository, making your changes, and issuing pull request on the `dev` branch. 6 | 7 | Any Pull request made directly to `master` or other branches will be closed. -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright 2017 Stormpath, Inc. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stormpath/sdk", 3 | "type": "library", 4 | "description": "A PHP wrapper for Stormpath's API", 5 | "keywords": [ 6 | "stormpath", 7 | "cloud", 8 | "security", 9 | "api", 10 | "user management", 11 | "user security", 12 | "group management", 13 | "authentication"], 14 | "homepage": "https://github.com/stormpath/stormpath-sdk-php", 15 | "license": "Apache-2.0", 16 | "authors": [ 17 | { 18 | "name": "Brian Retterer", 19 | "email": "brian@stormpath.com", 20 | "role": "Developer" 21 | }, 22 | { 23 | "name": "Elder Crisostomo", 24 | "email": "elder@stormpath.com", 25 | "role": "Developer" 26 | } 27 | ], 28 | "autoload": { 29 | "psr-4": { 30 | "Stormpath\\": "src/" 31 | } 32 | }, 33 | "autoload-dev": { 34 | "psr-4": { 35 | "Stormpath\\Tests\\": "tests/" 36 | } 37 | }, 38 | "require": { 39 | "php": ">=5.5", 40 | "firebase/php-jwt": "4.0.*", 41 | "phpseclib/phpseclib": "0.3.*|~1.0|~2.0", 42 | "cache/taggable-cache": "0.4.*", 43 | "cache/redis-adapter": "0.4.*", 44 | "cache/memcached-adapter": "0.3.*", 45 | "cache/array-adapter": "0.4.*", 46 | "cache/void-adapter": "0.3.*", 47 | "guzzlehttp/psr7": "^1.3", 48 | "psr/http-message": "^1.0", 49 | "php-http/httplug": "^1.0", 50 | "php-http/discovery": "^1.0", 51 | "php-http/curl-client": "^1.0", 52 | "php-http/message": "^1.3", 53 | "php-http/client-common": "^1.2" 54 | }, 55 | "require-dev": { 56 | "phpunit/phpunit": "4.*", 57 | "symfony/debug": "*", 58 | "symfony/var-dumper": "*" 59 | }, 60 | "suggest": { 61 | "php": ">=5.6" 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/ApiKey.php: -------------------------------------------------------------------------------- 1 | id = $id; 29 | $this->secret = $secret; 30 | } 31 | 32 | public function getId() 33 | { 34 | return $this->id; 35 | } 36 | 37 | public function getSecret() 38 | { 39 | return $this->secret; 40 | } 41 | 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/Authc/Api/ApiAuthenticationResult.php: -------------------------------------------------------------------------------- 1 | options = array(); 36 | 37 | if (isset($options[self::ENCRYPT_SECRET]) and $options[self::ENCRYPT_SECRET]) { 38 | $this->options[self::ENCRYPT_SECRET] = $options[self::ENCRYPT_SECRET]; 39 | 40 | $this->options[self::ENCRYPTION_KEY_SIZE] = isset($options[self::ENCRYPTION_KEY_SIZE]) ? 41 | $options[self::ENCRYPTION_KEY_SIZE] : 42 | self::DEFAULT_ENCRYPTION_KEY_SIZE; 43 | 44 | $this->options[self::ENCRYPTION_KEY_ITERATIONS] = isset($options[self::ENCRYPTION_KEY_ITERATIONS]) ? 45 | $options[self::ENCRYPTION_KEY_ITERATIONS] : 46 | self::DEFAULT_ENCRYPTION_KEY_ITERATIONS; 47 | 48 | $salt = openssl_random_pseudo_bytes(16); 49 | 50 | $this->options[self::ENCRYPTION_KEY_SALT] = ApiKeyEncryptionUtils::base64url_encode($salt); 51 | } 52 | } 53 | 54 | public function isEncryptSecret() 55 | { 56 | return isset($this->options[self::ENCRYPT_SECRET]) and $this->options[self::ENCRYPT_SECRET]; 57 | } 58 | 59 | public function getEncryptionKeySize() 60 | { 61 | return $this->options[self::ENCRYPTION_KEY_SIZE]; 62 | } 63 | 64 | public function getEncryptionKeyIterations() 65 | { 66 | return $this->options[self::ENCRYPTION_KEY_ITERATIONS]; 67 | } 68 | 69 | public function getEncryptionKeySalt() 70 | { 71 | return $this->options[self::ENCRYPTION_KEY_SALT]; 72 | } 73 | 74 | public function toArray() 75 | { 76 | return $this->options; 77 | } 78 | 79 | } -------------------------------------------------------------------------------- /src/Authc/Api/ApiKeyEncryptionUtils.php: -------------------------------------------------------------------------------- 1 | getEncryptionKeySalt()); 30 | $iterations = $options->getEncryptionKeyIterations(); 31 | $keyLengthBits = $options->getEncryptionKeySize(); 32 | $iv = substr($decodedSecret, 0, 16); 33 | 34 | if (class_exists('phpseclib\Crypt\AES')) { 35 | $aes = new ModernAES(); 36 | } else { 37 | $aes = new OldAES(); 38 | } 39 | 40 | $aes->setPassword($password, 'pbkdf2', 'sha1', $salt, $iterations, $keyLengthBits / 8); 41 | $aes->setKeyLength($keyLengthBits); 42 | $aes->setIV($iv); 43 | 44 | return $aes->decrypt(substr($decodedSecret, 16)); 45 | } 46 | 47 | public static function base64url_encode($data) 48 | { 49 | return rtrim(strtr(base64_encode($data), '+/', '-_'), '='); 50 | } 51 | 52 | public static function base64url_decode($data) 53 | { 54 | return base64_decode(str_pad(strtr($data, '-_', '+/'), 55 | strlen($data) % 4, '=', STR_PAD_RIGHT)); 56 | } 57 | 58 | /** 59 | * http://www.php.net/manual/en/ref.mcrypt.php#69782 60 | * 61 | * @param $text 62 | * @param $blocksize 63 | * @return string 64 | */ 65 | private function pkcs5_pad ($text, $blocksize) 66 | { 67 | $pad = $blocksize - (strlen($text) % $blocksize); 68 | return $text . str_repeat(chr($pad), $pad); 69 | } 70 | 71 | /** 72 | * http://www.php.net/manual/en/ref.mcrypt.php#69782 73 | * 74 | * @param $text 75 | * @param $blocksize 76 | * @return string 77 | */ 78 | private function pkcs5_unpad($text) 79 | { 80 | $pad = ord($text{strlen($text)-1}); 81 | if ($pad > strlen($text)) return false; 82 | if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) return false; 83 | return substr($text, 0, -1 * $pad); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/Authc/Api/ApiRequestAuthenticator.php: -------------------------------------------------------------------------------- 1 | hasAuthorizationHeader()) { 31 | if ($request->isBasicAuthorization()) { 32 | if ($request->hasGrantType()) { 33 | $authenticator = new OAuthClientCredentialsRequestAuthenticator($this->application); 34 | } else { 35 | $authenticator = new BasicRequestAuthenticator($this->application); 36 | } 37 | } else if ($request->isBearerAuthorization()) { 38 | $authenticator = new OAuthBearerRequestAuthenticator($this->application); 39 | } 40 | 41 | } 42 | 43 | if($authenticator) { 44 | $result = $authenticator->authenticate($request); 45 | $application = $result->getApplication(); 46 | $apiKey = $result->getApiKey(); 47 | $accessToken = null; 48 | if(method_exists($result, 'getAccessToken')) { 49 | $accessToken = $result->getAccessToken(); 50 | } 51 | 52 | return new ApiAuthenticationResult($application, $apiKey, $accessToken); 53 | } 54 | throw new RequestAuthenticatorException('The method of authentication you are trying is not an allowed method. 55 | Please make sure you are using one of the following methods for 56 | Authentication: Basic, OAuth Bearer, or OAuth Client Credentials.'); 57 | } 58 | } -------------------------------------------------------------------------------- /src/Authc/Api/AuthenticatorResult.php: -------------------------------------------------------------------------------- 1 | application = $application; 36 | 37 | $this->apiKey = $apiKey; 38 | 39 | if($accessToken) { 40 | $this->accessToken = $accessToken; 41 | } 42 | } 43 | 44 | public function getApplication() 45 | { 46 | return $this->application; 47 | } 48 | 49 | public function getApiKey() 50 | { 51 | return $this->apiKey; 52 | } 53 | 54 | public function getAccessToken() 55 | { 56 | return $this->accessToken; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Authc/Api/BasicAuthenticationResult.php: -------------------------------------------------------------------------------- 1 | application) 29 | throw new \InvalidArgumentException('The application must be set.'); 30 | 31 | $apiKey = $this->getApiKeyById($request); 32 | 33 | if($this->isValidApiKey($request, $apiKey)) 34 | { 35 | $account = $apiKey->account; 36 | } 37 | 38 | if($this->isValidAccount($account)) 39 | { 40 | return new BasicAuthenticationResult($this->application, $apiKey); 41 | } 42 | 43 | 44 | } 45 | 46 | 47 | } -------------------------------------------------------------------------------- /src/Authc/Api/InternalRequestAuthenticator.php: -------------------------------------------------------------------------------- 1 | application = $application; 31 | } 32 | 33 | /** 34 | * @param Request $request 35 | * @return null 36 | */ 37 | protected function getApiKeyById(Request $request) 38 | { 39 | return $this->application->getApiKey($request->getApiId()); 40 | } 41 | 42 | /** 43 | * @param Request $request 44 | * @param $apiKey 45 | * @throws RequestAuthenticatorException 46 | */ 47 | protected function isValidApiKey(Request $request, $apiKey) 48 | { 49 | if ($apiKey->getStatus() == 'DISABLED') 50 | throw new RequestAuthenticatorException('The API Key is not allowed to make this request.'); 51 | 52 | if($request->getScheme() == 'Bearer') 53 | return true; 54 | 55 | if ($apiKey === null || !!($request->getApiSecret() != $apiKey->getSecret())) 56 | throw new RequestAuthenticatorException('The API Key is not valid for this request.'); 57 | 58 | return true; 59 | } 60 | 61 | /** 62 | * @param $account 63 | * @throws RequestAuthenticatorException 64 | */ 65 | protected function isValidAccount($account) 66 | { 67 | if ($account->getStatus() == 'DISABLED') { 68 | throw new RequestAuthenticatorException('The Account you are authenticating with is not active.'); 69 | } 70 | 71 | return true; 72 | } 73 | 74 | } -------------------------------------------------------------------------------- /src/Authc/Api/OAuthAuthenticationResult.php: -------------------------------------------------------------------------------- 1 | application) 27 | throw new \InvalidArgumentException('The application must be set.'); 28 | 29 | $apiKey = $this->getApiKeyById($request); 30 | 31 | if($this->isValidApiKey($request, $apiKey)) 32 | { 33 | $account = $apiKey->account; 34 | } 35 | 36 | if($this->isValidAccount($account)) 37 | { 38 | return new OAuthBearerAuthenticationResult($this->application, $apiKey); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /src/Authc/Api/OAuthClientCredentialsAuthenticationResult.php: -------------------------------------------------------------------------------- 1 | application) 31 | throw new \InvalidArgumentException('The application must be set.'); 32 | 33 | $this->validateGrantType($request); 34 | 35 | $apiKey = $this->getApiKeyById($request); 36 | 37 | if($this->isValidApiKey($request, $apiKey)) 38 | { 39 | $account = $apiKey->account; 40 | } 41 | 42 | if($this->isValidAccount($account)) 43 | { 44 | $token = $this->buildTokenResponse($apiKey); 45 | 46 | return new OAuthClientCredentialsAuthenticationResult($this->application, $apiKey, $token); 47 | } 48 | } 49 | 50 | private function buildTokenResponse($apiKey) 51 | { 52 | $token = array( 53 | 'access_token' => $this->buildAccessToken($apiKey), 54 | 'token_type' => 'bearer', 55 | 'expires_in' => time() + 3600 56 | ); 57 | 58 | return json_encode($token); 59 | } 60 | 61 | private function buildAccessToken($apiKey) 62 | { 63 | $apiSecret = Client::getInstance()->getDataStore()->getApiKey()->getSecret(); 64 | $jwt = JWT::encode( 65 | array( 66 | "sub" => $apiKey->id, 67 | "iss" => $this->application->getHref(), 68 | "iat" => time(), 69 | "exp" => time() + 3600 70 | 71 | ), 72 | $apiSecret 73 | ); 74 | 75 | return $jwt; 76 | } 77 | 78 | private function validateGrantType($request) 79 | { 80 | if (!$request->isBasicAuthorization()) 81 | throw new RequestAuthenticatorException('The type of Authentication is incorrect!'); 82 | 83 | if (!$request->hasGrantType()) 84 | throw new RequestAuthenticatorException('The grant_type query parameter must be used'); 85 | } 86 | 87 | } -------------------------------------------------------------------------------- /src/Authc/Api/OAuthRequestAuthenticator.php: -------------------------------------------------------------------------------- 1 | hasAuthorizationHeader()) { 31 | if ($request->isBasicAuthorization()) { 32 | if ($request->hasGrantType()) { 33 | $authenticator = new OAuthClientCredentialsRequestAuthenticator($this->application); 34 | } 35 | } else if ($request->isBearerAuthorization()) { 36 | $authenticator = new OAuthBearerRequestAuthenticator($this->application); 37 | } 38 | 39 | } 40 | 41 | if($authenticator) { 42 | $result = $authenticator->authenticate($request); 43 | $application = $result->getApplication(); 44 | $apiKey = $result->getApiKey(); 45 | $accessToken = null; 46 | if(method_exists($result, 'getAccessToken')) { 47 | $accessToken = $result->getAccessToken(); 48 | } 49 | 50 | return new OAuthAuthenticationResult($application, $apiKey, $accessToken); 51 | } 52 | 53 | throw new RequestAuthenticatorException('The method of authentication you are trying is not an allowed method. 54 | Please make sure you are using one of the following methods for 55 | Authentication: OAuth Bearer, or OAuth Client Credentials.'); 56 | } 57 | } -------------------------------------------------------------------------------- /src/Authc/Api/RequestAuthenticator.php: -------------------------------------------------------------------------------- 1 | dataStore = $dataStore; 32 | } 33 | 34 | public function authenticate($parentHref, AuthenticationRequest $request, array $options = array()) 35 | { 36 | if (!$parentHref) 37 | { 38 | throw new \InvalidArgumentException('$parentHref argument must be specified'); 39 | } 40 | 41 | if (!($request instanceof UsernamePasswordRequest)) 42 | { 43 | throw new \InvalidArgumentException('Only UsernamePasswordRequest instances are supported.'); 44 | } 45 | 46 | $username = $request->getPrincipals(); 47 | $username = $username ? $username : ''; 48 | 49 | $password = $request->getCredentials(); 50 | $password = implode('', $password); 51 | 52 | $value = $username .':' .$password; 53 | 54 | $value = base64_encode($value); 55 | 56 | $attempt = $this->dataStore->instantiate(Stormpath::BASIC_LOGIN_ATTEMPT); 57 | $attempt->setValue($value); 58 | 59 | if ($request->getAccountStore() != null) { 60 | $attempt->setAccountStore($request->getAccountStore()); 61 | } 62 | 63 | $href = $parentHref . '/loginAttempts'; 64 | 65 | return $this->dataStore->create($href, $attempt, Stormpath::AUTHENTICATION_RESULT, $options); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Authc/UsernamePasswordRequest.php: -------------------------------------------------------------------------------- 1 | password = $password ? str_split($password) : array(); 34 | $this->username = $username; 35 | 36 | $this->host = isset($options['host']) ? $options['host'] : null; 37 | 38 | if (isset($options['accountStore'])) 39 | { 40 | $accountStore = $options['accountStore']; 41 | if ($accountStore instanceof AccountStore) 42 | { 43 | $this->accountStore = $accountStore; 44 | } 45 | else 46 | { 47 | throw new \InvalidArgumentException("The value for accountStore in the \$options array should be an instance of \\Stormpath\\Resource\\AccountStore"); 48 | } 49 | } 50 | } 51 | 52 | public function getPrincipals() 53 | { 54 | return $this->username; 55 | } 56 | 57 | public function getCredentials() 58 | { 59 | return $this->password; 60 | } 61 | 62 | public function getAccountStore() 63 | { 64 | return $this->accountStore; 65 | } 66 | 67 | // @codeCoverageIgnoreStart 68 | public function getHost() 69 | { 70 | return $this->host; 71 | } 72 | 73 | /** 74 | * Clears out (nulls) the username, password, and options. The password bytes are explicitly set to 75 | * 0x00 to eliminate the possibility of memory access at a later time. 76 | */ 77 | public function clear() 78 | { 79 | $this->host = null; 80 | $this->username = null; 81 | 82 | $password = $this->password; 83 | 84 | $this->password = null; 85 | 86 | if ($password) 87 | { 88 | foreach($password as $char) 89 | { 90 | $char = 0x00; 91 | } 92 | } 93 | } 94 | // @codeCoverageIgnoreEnd 95 | 96 | } 97 | -------------------------------------------------------------------------------- /src/Cache/ArrayCacheManager.php: -------------------------------------------------------------------------------- 1 | itemToCache = $itemToCache; 28 | } 29 | 30 | public function setCachedItem($itemToCache) { 31 | $this->itemToCache = $itemToCache; 32 | } 33 | 34 | public function getCachedItem() { 35 | return $this->itemToCache; 36 | } 37 | 38 | public function addMetaItem($key, $value) { 39 | $this->cachedItemMeta[$key] = $value; 40 | } 41 | 42 | public function getMetaItem($key) { 43 | if(! key_exists($key, $this->cachedItemMeta)) { 44 | return null; 45 | } 46 | 47 | return $this->cachedItemMeta[$key]; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/Cache/CacheManager.php: -------------------------------------------------------------------------------- 1 | cache = $cache; 30 | } 31 | 32 | protected function fetchObjectFromCache($key) 33 | { 34 | if (false === $result = unserialize($this->cache->get($key))) { 35 | return [false, null]; 36 | } 37 | 38 | return $result; 39 | } 40 | 41 | protected function clearAllObjectsFromCache() 42 | { 43 | return $this->cache->clear(); 44 | } 45 | 46 | protected function clearOneObjectFromCache($key) 47 | { 48 | return $this->cache->delete($key); 49 | } 50 | 51 | protected function storeItemInCache(CacheItemInterface $item, $ttl) 52 | { 53 | $key = $item->getKey(); 54 | $data = serialize([true, $item->get()]); 55 | return $this->cache->put($key, $data, $ttl/60); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Cache/Cacheable.php: -------------------------------------------------------------------------------- 1 | items)) $cache = false; 31 | 32 | // We dont want to cache if it does not have a href. 33 | if(!isset($resource->href)) $cache = false; 34 | 35 | // Do Not Cache something with ONLY 1 item (href only typically) 36 | if(count((array)$resource) == 1) $cache = false; 37 | 38 | return $cache; 39 | 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/Cache/MemcachedCacheManager.php: -------------------------------------------------------------------------------- 1 | addServers($options['memcached']); 30 | 31 | return new MemcachedCachePool($memcached); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Cache/NullCacheManager.php: -------------------------------------------------------------------------------- 1 | $value) { 28 | $query[$key] = (string) $value; 29 | } 30 | $query = http_build_query($query); 31 | } 32 | $key = $href.'?'.$query; 33 | if(!empty($options)) { 34 | $key .= '_' . implode('_',$options); 35 | } 36 | $key = preg_replace('/[^0-9A-Za-z\_\.]/', '', $key); 37 | return $key; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Cache/PSR6CacheManagerInterface.php: -------------------------------------------------------------------------------- 1 | pool = $pool; 29 | } 30 | 31 | public function getCachePool($options) 32 | { 33 | return $this->pool; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Cache/RedisCacheManager.php: -------------------------------------------------------------------------------- 1 | connect($options['redis']['host']); 30 | $redis->auth($options['redis']['password']); 31 | 32 | return new RedisCachePool($redis); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Cache/Tags/CacheTagExtractor.php: -------------------------------------------------------------------------------- 1 | href)) { 28 | $cacheTags[] = $document->href; 29 | } 30 | 31 | foreach ($document as $key => $value) { 32 | if (is_object($value) && isset($value->href)) { 33 | $cacheTags = array_merge(self::extractCacheTags($value), $cacheTags); 34 | } 35 | 36 | if ($key === 'items') { 37 | foreach ($value as $item) { 38 | $cacheTags = array_merge(self::extractCacheTags($item), $cacheTags); 39 | } 40 | } 41 | } 42 | 43 | return $cacheTags; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/DataStore/ClassNameResolver.php: -------------------------------------------------------------------------------- 1 | DataStore to resolve the class name of a resource 24 | * to instantiate. 25 | * 26 | * @package Stormpath\DataStore 27 | */ 28 | interface ClassNameResolver 29 | { 30 | /** 31 | * @param $className 32 | * @param array $options 33 | */ 34 | public function resolve($className, $data, array $options = array()); 35 | } -------------------------------------------------------------------------------- /src/DataStore/DataStore.php: -------------------------------------------------------------------------------- 1 | 27 | * This method effectively replaces the new keyword that would have been used otherwise if the concrete 28 | * implementation was known (Resource implementation classes are intentionally not exposed to SDK end-users). 29 | * 30 | * @param $className the Resource class name (as a String) to instantiate. This can be the fully qualified name or the 31 | * simple name of the Resource (which is also the simple name of the .php file). 32 | * @param object $properties the optional Properties of the Resource to instantiate. 33 | * @param array options the options to create the resource. This optional argument is useful to specify query strings, 34 | * among other options. 35 | * 36 | * @return a new instance of the specified Resource. 37 | */ 38 | public function instantiate($className, \stdClass $properties = null, array $options = array()); 39 | 40 | /** 41 | * Looks up (retrieves) the resource at the specified href URL and returns the resource as an instance 42 | * of the specified class name. 43 | *

44 | * The $className argument must represent the name of an interface that is a sub-interface of 45 | * Resource, for example {@link Stormpath\Resource\Account}, {@link Stormpath\Resource\Directory}, etc. 46 | * 47 | * @param href the resource URL of the resource to retrieve 48 | * @param class the Resource sub-interface to instantiate. This can be the fully qualified name or the 49 | * simple name of the Resource (which is also the simple name of the .php file). 50 | * @param array options the options to create the resource. This optional argument is useful to specify query strings, 51 | * among other options. 52 | * @return an instance of the specified class based on the data returned from the specified {@code href} URL. 53 | */ 54 | public function getResource($href, $className, array $options = array()); 55 | } -------------------------------------------------------------------------------- /src/DataStore/DefaultClassNameResolver.php: -------------------------------------------------------------------------------- 1 | DataStore to resolve the class name of a resource 26 | * to instantiate based on the value of a property in the data set received. 27 | * 28 | * @package Stormpath\DataStore 29 | */ 30 | class DefaultClassNameResolver implements ClassNameResolver 31 | { 32 | 33 | const PROPERTY_ID = "propertyId"; 34 | 35 | private static $instance; 36 | private $delegates; 37 | 38 | private function __construct() 39 | { 40 | $this->delegates = array( 41 | Stormpath::PROVIDER_DATA => new ProviderDataClassNameResolver() 42 | ); 43 | } 44 | 45 | public static function getInstance() 46 | { 47 | if (is_null(self::$instance)) 48 | { 49 | self::$instance = new self(); 50 | } 51 | 52 | return self::$instance; 53 | } 54 | 55 | /** 56 | * Resolves a className to instantiate based on a property value that comes in the 57 | * received data set. The class to instantiate is a child in the class hierarchy of 58 | * the given $className. 59 | * 60 | * @param $className hierarchy parent of the child class that is getting resolved. 61 | * @param $data the received data set. 62 | * @param array $options contains the name of the property (propertyId) 63 | * that is going to be used to resolve the child class to instantiate. 64 | * @return resolved className 65 | */ 66 | public function resolve($className, $data, array $options = array()) 67 | { 68 | if (isset($options[DefaultClassNameResolver::PROPERTY_ID])) 69 | { 70 | if (isset($this->delegates[$className])) 71 | { 72 | $classNameResolver = $this->delegates[$className]; 73 | return $classNameResolver->resolve($className, $data, $options); 74 | } 75 | else 76 | { 77 | throw new \InvalidArgumentException("No delegate resolver found for className ".$className); 78 | } 79 | 80 | } 81 | else 82 | { 83 | return $className; 84 | } 85 | } 86 | } -------------------------------------------------------------------------------- /src/DataStore/DefaultResourceFactory.php: -------------------------------------------------------------------------------- 1 | dataStore = $dataStore; 34 | } 35 | 36 | public function instantiate($className, array $constructorArgs) 37 | { 38 | 39 | $class = new \ReflectionClass($this->qualifyClassName($className)); 40 | 41 | array_unshift($constructorArgs, $this->dataStore); 42 | 43 | $newClass = $class->newInstanceArgs($constructorArgs); 44 | 45 | if($class->hasConstant ( "CUSTOM_DATA" )) 46 | { 47 | $newClass->customData; 48 | } 49 | 50 | if($newClass instanceof \Stormpath\Resource\SamlProvider) { 51 | $newClass = $this->convertSamlAttributeStatementMappingRules($newClass); 52 | } 53 | 54 | return $newClass; 55 | } 56 | 57 | private function qualifyClassName($className) 58 | { 59 | if (class_exists($className) && strstr($className, 'Stormpath')) { 60 | return $className; 61 | } 62 | 63 | if (strpos($className, self::RESOURCE_PATH) === false) 64 | { 65 | return self::RESOURCE_PATH .$className; 66 | } 67 | 68 | return $className; 69 | 70 | } 71 | 72 | private function convertSamlAttributeStatementMappingRules($newClass) 73 | { 74 | $mappingRules = $newClass->getAttributeStatementMappingRules(); 75 | if(null === $mappingRules) { 76 | return $newClass; 77 | } 78 | 79 | $items = $mappingRules->getItems(); 80 | $newItems = []; 81 | 82 | $itemBuilder = new AttributeStatementMappingRuleBuilder(); 83 | foreach($items as $item) { 84 | $newItems[] = $itemBuilder->setName($item->name) 85 | ->setNameFormat($item->nameFormat) 86 | ->setAccountAttributes($item->accountAttributes) 87 | ->build(); 88 | } 89 | 90 | $newClass->getAttributeStatementMappingRules()->items = $newItems; 91 | return $newClass; 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /src/DataStore/InternalDataStore.php: -------------------------------------------------------------------------------- 1 | 26 | * WARNING: This API CAN CHANGE AT ANY TIME, WITHOUT NOTICE. DO NOT DEPEND ON IT. 27 | * 28 | */ 29 | 30 | interface InternalDataStore extends DataStore 31 | { 32 | 33 | public function create($parentHref, Resource $resource, $returnType, array $options = array()); 34 | 35 | public function save(Resource $resource, $returnType = null); 36 | 37 | public function delete(Resource $resource); 38 | 39 | public function getApiKey(); 40 | 41 | } -------------------------------------------------------------------------------- /src/DataStore/ResourceFactory.php: -------------------------------------------------------------------------------- 1 | getProperty(self::RESET_TOKEN_TTL); 44 | } 45 | 46 | public function setResetTokenTtl($ttl) 47 | { 48 | $this->setProperty(self::RESET_TOKEN_TTL, $ttl); 49 | } 50 | 51 | public function getResetEmailStatus() 52 | { 53 | return $this->getProperty(self::RESET_EMAIL_STATUS); 54 | } 55 | 56 | public function setResetEmailStatus($ttl) 57 | { 58 | $this->setProperty(self::RESET_EMAIL_STATUS, $ttl); 59 | } 60 | 61 | public function getResetSuccessEmailStatus() 62 | { 63 | return $this->getProperty(self::RESET_EMAIL_STATUS); 64 | } 65 | 66 | public function setResetSuccessEmailStatus($ttl) 67 | { 68 | $this->setProperty(self::RESET_EMAIL_STATUS, $ttl); 69 | } 70 | 71 | public function getStrength(array $options = []) 72 | { 73 | return $this->getResourceProperty(self::PASSWORD_STRENGTH, Stormpath::PASSWORD_STRENGTH, $options); 74 | } 75 | 76 | public function getResetEmailTemplates(array $options = []) 77 | { 78 | return $this->getResourceProperty(self::RESET_EMAIL_TEMPLATES, Stormpath::MODELED_EMAIL_TEMPLATE_LIST, $options); 79 | } 80 | 81 | public function getResetSuccessEmailTemplates(array $options = []) 82 | { 83 | return $this->getResourceProperty(self::RESET_SUCCESS_EMAIL_TEMPLATES, Stormpath::UNMODELED_EMAIL_TEMPLATE_LIST, $options); 84 | } 85 | 86 | 87 | } -------------------------------------------------------------------------------- /src/Exceptions/Cache/InvalidCacheManagerException.php: -------------------------------------------------------------------------------- 1 | apiKey = $apiKey; 42 | } 43 | 44 | public function authenticate(RequestInterface $request) 45 | { 46 | $date = new \DateTime(); 47 | $date->setTimezone(new \DateTimeZone(self::TIME_ZONE)); 48 | $timeStamp = $date->format(self::TIMESTAMP_FORMAT); 49 | 50 | $authorizationHeader = base64_encode($this->apiKey->getId() . ":" . $this->apiKey->getSecret()); 51 | 52 | return $request 53 | ->withHeader(self::STORMPATH_DATE_HEADER, $timeStamp) 54 | ->withHeader(self::AUTHORIZATION_HEADER, self::AUTHENTICATION_SCHEME . " " . $authorizationHeader) 55 | ; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/Mail/ModeledEmailTemplate.php: -------------------------------------------------------------------------------- 1 | getProperty(self::DEFAULT_MODEL); 34 | } 35 | 36 | /** 37 | * Sets the defaultModel property 38 | * 39 | * @param array $defaultModel The defaultModel of the object 40 | * @return self 41 | */ 42 | public function setDefaultModel($defaultModel) 43 | { 44 | $this->setProperty(self::DEFAULT_MODEL, $defaultModel); 45 | 46 | return $this; 47 | } 48 | 49 | /** 50 | * Return the clickable URL that the user will receive inside the email. 51 | * This is just a convenience method for getting the `linkBaseUrl` out of 52 | * the `default model` array. 53 | * 54 | * @return null|string the URL the user will be taken to once they click on the URL received in the email. 55 | */ 56 | public function getLinkBaseUrl() 57 | { 58 | $defaultModel = (array)$this->getDefaultModel(); 59 | 60 | if(empty($defaultModel) || !key_exists(self::LINK_BASE_URL, $defaultModel)) { 61 | return null; 62 | } 63 | 64 | return $defaultModel[self::LINK_BASE_URL]; 65 | } 66 | 67 | /** 68 | * Convenience method to specify the clickable url that the user will receive 69 | * inside the email. For Example, in the reset password workflow, this url 70 | * should point to the form where the user can insert their new password. 71 | * 72 | * @param string $linkBaseUrl the URL the user will be taken to once they click on the URL received in the email. 73 | * @return $this 74 | */ 75 | public function setLinkBaseUrl($linkBaseUrl) 76 | { 77 | $defaultModel = $this->getDefaultModel(); 78 | 79 | $defaultModel[self::LINK_BASE_URL] = $linkBaseUrl; 80 | 81 | $this->setDefaultModel($defaultModel); 82 | 83 | return $this; 84 | } 85 | 86 | /** 87 | * Save the model, Ultimately, this will call the parent save, but we want to 88 | * make sure the `linkBaseUrl` is set and not null first. This is required 89 | * by Stormpath to not be null when saving. 90 | * 91 | * @throws \InvalidArgumentException 92 | */ 93 | public function save() 94 | { 95 | if(null === $this->getLinkBaseUrl()) { 96 | throw new \InvalidArgumentException('The defaultModel must contain the "linkBaseUrl" reserved property'); 97 | } 98 | 99 | parent::save(); 100 | 101 | return; 102 | } 103 | 104 | } -------------------------------------------------------------------------------- /src/Mail/ModeledEmailTemplateList.php: -------------------------------------------------------------------------------- 1 | type)) { 29 | case 'sms' : 30 | return $this->dataStore->instantiate(Stormpath::SMS_FACTOR, $properties); 31 | case 'google-authenticator' : 32 | return $this->dataStore->instantiate(Stormpath::GOOGLE_AUTHENTICATOR_FACTOR, $properties); 33 | } 34 | 35 | return $this->dataStore->instantiate($className, $properties); 36 | 37 | } 38 | 39 | function getItemClassName() 40 | { 41 | return Stormpath::FACTOR; 42 | } 43 | } -------------------------------------------------------------------------------- /src/Mfa/GoogleAuthenticatorChallenge.php: -------------------------------------------------------------------------------- 1 | setCode($code); 47 | 48 | $returnedChallenge = $this->getDataStore()->save($this, Stormpath::GOOGLE_AUTHENTICATOR_CHALLENGE); 49 | 50 | if($returnedChallenge->getStatus() == Stormpath::SUCCESS) { 51 | return $returnedChallenge; 52 | } 53 | 54 | return false; 55 | } 56 | 57 | 58 | } -------------------------------------------------------------------------------- /src/Mfa/PhoneList.php: -------------------------------------------------------------------------------- 1 | getProperty(self::MESSAGE); 48 | } 49 | 50 | /** 51 | * Sets the message property. 52 | * 53 | * @param string $message The message of the object. 54 | * @return self 55 | */ 56 | public function setMessage($message) 57 | { 58 | if(!strpos($message, Stormpath::MFA_CHALLENGE_CODE_PLACEHOLDER)) { 59 | throw new \InvalidArgumentException('The message must contain a code placeholder: ' . Stormpath::MFA_CHALLENGE_CODE_PLACEHOLDER); 60 | } 61 | 62 | $this->setProperty(self::MESSAGE, $message); 63 | 64 | return $this; 65 | } 66 | 67 | /** 68 | * Validate the current Challenge. 69 | * 70 | * @param string $code The code to validate the challenge with. 71 | * @return SmsChallenge|boolean 72 | */ 73 | public function validate($code) 74 | { 75 | $this->setCode($code); 76 | 77 | $returnedChallenge = $this->getDataStore()->save($this, Stormpath::SMS_CHALLENGE); 78 | 79 | if($returnedChallenge->getStatus() == Stormpath::SUCCESS) { 80 | return $returnedChallenge; 81 | } 82 | 83 | return false; 84 | } 85 | 86 | 87 | } -------------------------------------------------------------------------------- /src/Oauth/ExchangeIdSiteTokenAttempt.php: -------------------------------------------------------------------------------- 1 | setProperty(self::TOKEN, $token); 31 | return $this; 32 | } 33 | 34 | public function setGrantType($grantType) { 35 | $this->setProperty(self::GRANT_TYPE, $grantType); 36 | return $this; 37 | } 38 | 39 | public function getToken() { 40 | return $this->getProperty(self::TOKEN); 41 | } 42 | 43 | public function getGrantType() { 44 | return $this->getProperty(self::REFRESH_TOKEN); 45 | } 46 | } -------------------------------------------------------------------------------- /src/Oauth/ExchangeIdSiteTokenAuthenticator.php: -------------------------------------------------------------------------------- 1 | application = $application; 37 | } 38 | 39 | public function authenticate(ExchangeIdSiteTokenRequest $exchangeIdSiteTokenRequest) 40 | { 41 | $attempt = new ExchangeIdSiteTokenAttempt(); 42 | $attempt->setGrantType($exchangeIdSiteTokenRequest->getGrantType()) 43 | ->setToken($exchangeIdSiteTokenRequest->getToken()); 44 | 45 | $grantResult = $this->application->dataStore->create( 46 | $this->application->getHref() . self::OAUTH_TOKEN_PATH, 47 | $attempt, 48 | \Stormpath\Stormpath::GRANT_AUTHENTICATION_TOKEN 49 | ); 50 | 51 | $builder = new OauthGrantAuthenticationResultBuilder($grantResult); 52 | return $builder->build(); 53 | } 54 | } -------------------------------------------------------------------------------- /src/Oauth/ExchangeIdSiteTokenRequest.php: -------------------------------------------------------------------------------- 1 | token = $Token; 31 | } 32 | 33 | public function getToken() { 34 | return $this->token; 35 | } 36 | 37 | public function getGrantType() { 38 | return $this->grant_type; 39 | } 40 | } -------------------------------------------------------------------------------- /src/Oauth/OauthGrantAuthenticationResult.php: -------------------------------------------------------------------------------- 1 | accessToken = $builder->getAccessToken(); 36 | $this->accessTokenString = $builder->getAccessTokenString(); 37 | $this->refreshToken = $builder->getRefreshToken(); 38 | $this->refreshTokenString = $builder->getRefreshTokenString(); 39 | $this->accessTokenHref = $builder->getAccessTokenHref(); 40 | $this->tokenType = $builder->getTokenType(); 41 | $this->expiresIn = $builder->getExpiresIn(); 42 | } 43 | 44 | public function getAccessToken() { 45 | return $this->accessToken; 46 | } 47 | 48 | public function getRefreshTokenString() { 49 | return $this->refreshTokenString; 50 | } 51 | 52 | public function getRefreshToken() { 53 | return $this->refreshToken; 54 | } 55 | 56 | public function getAccessTokenHref() { 57 | return $this->accessTokenHref; 58 | } 59 | 60 | public function getTokenType() { 61 | return $this->tokenType; 62 | } 63 | 64 | public function getExpiresIn() { 65 | return $this->expiresIn; 66 | } 67 | 68 | public function getAccessTokenString() { 69 | return $this->accessTokenString; 70 | } 71 | } -------------------------------------------------------------------------------- /src/Oauth/OauthGrantAuthenticationResultBuilder.php: -------------------------------------------------------------------------------- 1 | grantAuthenticationToken = $grantAuthenticationToken; 40 | } 41 | 42 | public function getAccessToken() { 43 | return $this->accessToken; 44 | } 45 | 46 | public function getAccessTokenString() { 47 | return $this->accessTokenString; 48 | } 49 | 50 | public function getRefreshToken() { 51 | return $this->refreshToken; 52 | } 53 | 54 | public function getRefreshTokenString() { 55 | return $this->refreshTokenString; 56 | } 57 | 58 | public function getAccessTokenHref() { 59 | return $this->accessTokenHref; 60 | } 61 | 62 | public function getTokenType() { 63 | return $this->tokenType; 64 | } 65 | 66 | public function getExpiresIn() { 67 | return $this->expiresIn; 68 | } 69 | 70 | public function setIsRefreshAuthGrantRequest($bool) 71 | { 72 | $this->isRefreshGrantAuthRequest = $bool; 73 | return $this; 74 | } 75 | 76 | public function build() 77 | { 78 | $this->accessToken = $this->grantAuthenticationToken->getAsAccessToken(); 79 | $this->accessTokenString = $this->grantAuthenticationToken->getAccessToken(); 80 | $this->refreshTokenString = $this->grantAuthenticationToken->getRefreshToken(); 81 | $this->accessTokenHref = $this->grantAuthenticationToken->getAccessTokenHref(); 82 | $this->tokenType = $this->grantAuthenticationToken->getTokenType(); 83 | $this->expiresIn = $this->grantAuthenticationToken->getExpiresIn(); 84 | $this->refreshToken = $this->grantAuthenticationToken->getAsRefreshToken(); 85 | 86 | return new OauthGrantAuthenticationResult($this); 87 | } 88 | } -------------------------------------------------------------------------------- /src/Oauth/PasswordGrantAuthenticationAttempt.php: -------------------------------------------------------------------------------- 1 | setProperty(self::LOGIN, $login); 42 | 43 | return $this; 44 | } 45 | 46 | 47 | /** 48 | * @param string $password 49 | * @return $this 50 | */ 51 | public function setPassword($password) { 52 | $this->setProperty(self::PASSWORD, $password); 53 | 54 | return $this; 55 | } 56 | 57 | /** 58 | * @param string $grantType 59 | * @return $this 60 | */ 61 | public function setGrantType($grantType) { 62 | $this->setProperty(self::GRANT_TYPE, $grantType); 63 | 64 | return $this; 65 | } 66 | 67 | /** 68 | * @param string $organizationNameKey 69 | * @return $this 70 | */ 71 | public function setOrganizationNameKey($organizationNameKey) { 72 | $this->setProperty(self::ORGANIZATION_NAME_KEY, $organizationNameKey); 73 | 74 | return $this; 75 | } 76 | 77 | /** 78 | * @param AccountStore $accountStore 79 | */ 80 | public function setAccountStore(AccountStore $accountStore) { 81 | $this->setProperty(self::ACCOUNT_STORE_HREF, $accountStore->getHref()); 82 | 83 | return $this; 84 | } 85 | 86 | /** 87 | * @return string 88 | */ 89 | public function getLogin() { 90 | return $this->getProperty(self::LOGIN); 91 | } 92 | 93 | /** 94 | * @return string 95 | */ 96 | public function getPassword() { 97 | return $this->getProperty(self::PASSWORD); 98 | } 99 | 100 | /** 101 | * @return string 102 | */ 103 | public function getGrantType(){ 104 | return $this->getProperty(self::GRANT_TYPE); 105 | } 106 | 107 | /** 108 | * @return string 109 | */ 110 | public function getAccountStoreHref() { 111 | return $this->getProperty(self::ACCOUNT_STORE_HREF); 112 | } 113 | } -------------------------------------------------------------------------------- /src/Oauth/PasswordGrantAuthenticator.php: -------------------------------------------------------------------------------- 1 | application = $application; 33 | } 34 | 35 | public function authenticate(PasswordGrantRequest $passwordGrantRequest) 36 | { 37 | $passwordGrantAuthenticationAttempt = new PasswordGrantAuthenticationAttempt(); 38 | $passwordGrantAuthenticationAttempt->setLogin($passwordGrantRequest->getLogin()) 39 | ->setPassword($passwordGrantRequest->getPassword()) 40 | ->setGrantType($passwordGrantRequest->getGrantType()) 41 | ->setOrganizationNameKey($passwordGrantRequest->getOrgNameKey()); 42 | if($passwordGrantRequest->getAccountStore() != null) 43 | $passwordGrantAuthenticationAttempt->setAccountStore($passwordGrantRequest->getAccountStore()); 44 | 45 | $grantResult = $this->application->dataStore->create( 46 | $this->application->getHref() . self::OAUTH_TOKEN_PATH, 47 | $passwordGrantAuthenticationAttempt, 48 | \Stormpath\Stormpath::GRANT_AUTHENTICATION_TOKEN 49 | ); 50 | 51 | $builder = new OauthGrantAuthenticationResultBuilder($grantResult); 52 | return $builder->build(); 53 | 54 | } 55 | } -------------------------------------------------------------------------------- /src/Oauth/PasswordGrantRequest.php: -------------------------------------------------------------------------------- 1 | login = $login; 61 | $this->password = $password; 62 | $this->orgNameKey = $orgNameKey; 63 | } 64 | 65 | /** 66 | * @param AccountStore $accountStore 67 | * @return $this 68 | */ 69 | public function setAccountStore(AccountStore $accountStore) 70 | { 71 | $this->accountStore = $accountStore; 72 | 73 | return $this; 74 | } 75 | 76 | /** 77 | * @return string 78 | */ 79 | public function getPassword() 80 | { 81 | return $this->password; 82 | } 83 | 84 | /** 85 | * @return string 86 | */ 87 | public function getLogin() 88 | { 89 | return $this->login; 90 | } 91 | 92 | /** 93 | * @return string 94 | */ 95 | public function getOrgNameKey() 96 | { 97 | return $this->orgNameKey; 98 | } 99 | 100 | /** 101 | * @return mixed 102 | */ 103 | public function getAccountStore() 104 | { 105 | return $this->accountStore; 106 | } 107 | 108 | /** 109 | * @return string 110 | */ 111 | public function getGrantType() 112 | { 113 | return $this->grant_type; 114 | } 115 | } -------------------------------------------------------------------------------- /src/Oauth/RefreshGrantAuthenticationAttempt.php: -------------------------------------------------------------------------------- 1 | setProperty(self::REFRESH_TOKEN, $refreshToken); 31 | return $this; 32 | } 33 | 34 | public function setGrantType($grantType) { 35 | $this->setProperty(self::GRANT_TYPE, $grantType); 36 | return $this; 37 | } 38 | 39 | public function getRefreshToken() { 40 | return $this->getProperty(self::REFRESH_TOKEN); 41 | } 42 | 43 | public function getGrantType() { 44 | return $this->getProperty(self::REFRESH_TOKEN); 45 | } 46 | } -------------------------------------------------------------------------------- /src/Oauth/RefreshGrantAuthenticator.php: -------------------------------------------------------------------------------- 1 | application = $application; 37 | } 38 | 39 | public function authenticate(RefreshGrantRequest $refreshGrantRequest) 40 | { 41 | $attempt = new RefreshGrantAuthenticationAttempt(); 42 | $attempt->setGrantType($refreshGrantRequest->getGrantType()) 43 | ->setRefreshToken($refreshGrantRequest->getRefreshToken()); 44 | 45 | $grantResult = $this->application->dataStore->create( 46 | $this->application->getHref() . self::OAUTH_TOKEN_PATH, 47 | $attempt, 48 | \Stormpath\Stormpath::GRANT_AUTHENTICATION_TOKEN 49 | ); 50 | 51 | $builder = new OauthGrantAuthenticationResultBuilder($grantResult); 52 | $builder->setIsRefreshAuthGrantRequest(true); 53 | return $builder->build(); 54 | } 55 | } -------------------------------------------------------------------------------- /src/Oauth/RefreshGrantRequest.php: -------------------------------------------------------------------------------- 1 | refresh_token = $refreshToken; 31 | } 32 | 33 | public function getRefreshToken() { 34 | return $this->refresh_token; 35 | } 36 | 37 | public function getGrantType() { 38 | return $this->grant_type; 39 | } 40 | } -------------------------------------------------------------------------------- /src/Oauth/VerifyAccessToken.php: -------------------------------------------------------------------------------- 1 | application = $application; 40 | $this->localValidation = $localValidation; 41 | } 42 | 43 | public function verify($jwt = null) 44 | { 45 | // JWT was not passed in 46 | if(!$jwt) { 47 | $jwt = $this->retrieveJwtFromHeader(); 48 | } 49 | 50 | // JWT was not in header 51 | if(!$jwt) { 52 | $jwt = $this->retrieveJwtFromCookie(); 53 | } 54 | 55 | // JWT not in Header or Cookie 56 | if(!$jwt) { 57 | throw new \InvalidArgumentException('Could not find access token, please pass in JWT'); 58 | } 59 | 60 | if($this->localValidation) 61 | return JWT::decode($jwt, $this->application->dataStore->getApiKey()->getSecret(), ['HS256']); 62 | 63 | $href = $this->application->getHref() . '/authTokens/' . $jwt; 64 | 65 | return $this->application->dataStore->getResource($href, Stormpath::ACCESS_TOKEN); 66 | 67 | } 68 | 69 | public function withLocalValidation() 70 | { 71 | $this->localValidation = true; 72 | return $this; 73 | } 74 | 75 | private function retrieveJwtFromHeader() 76 | { 77 | if(!isset($_SERVER['HTTP_AUTHORIZATION'])) 78 | return null; 79 | 80 | $authHeader = $_SERVER['HTTP_AUTHORIZATION']; 81 | $headerParts = explode(' ', $authHeader); 82 | 83 | if(count($headerParts) != 2) 84 | throw new \InvalidArgumentException('Authorization Header invalid.'); 85 | 86 | if($headerParts[0] != 'Bearer') 87 | throw new \InvalidArgumentException('Authorization Header invalid Type'); 88 | 89 | return $headerParts[1]; 90 | } 91 | 92 | private function retrieveJwtFromCookie() 93 | { 94 | if(!isset($_COOKIE['access_token'])) 95 | return null; 96 | 97 | return $_COOKIE['access_token']; 98 | } 99 | } -------------------------------------------------------------------------------- /src/Provider/FacebookProviderAccountRequest.php: -------------------------------------------------------------------------------- 1 | options = $options; 37 | } 38 | 39 | /** 40 | * Loads a given instance of ProviderData with the properties 41 | * stored internally in the request 42 | * 43 | * @param ProviderData $providerData the instance to load with data 44 | * @return ProviderData the given instance with properties set 45 | */ 46 | function getProviderData() 47 | { 48 | $providerData = new FacebookProviderData(); 49 | 50 | $providerData->providerId = FacebookProviderData::PROVIDER_ID; 51 | 52 | if (isset($this->options[self::CODE])) 53 | { 54 | $providerData->code = $this->options[self::CODE]; 55 | } 56 | else if (isset($this->options[self::ACCESS_TOKEN])) 57 | { 58 | $providerData->accessToken = $this->options[self::ACCESS_TOKEN]; 59 | } 60 | else 61 | { 62 | throw new \InvalidArgumentException('Either code or accessToken must be set for FacebookProviderAccountRequest'); 63 | } 64 | 65 | return $providerData; 66 | } 67 | } -------------------------------------------------------------------------------- /src/Provider/GithubProviderAccountRequest.php: -------------------------------------------------------------------------------- 1 | options = $options; 37 | } 38 | 39 | /** 40 | * Loads a given instance of ProviderData with the properties 41 | * stored internally in the request 42 | * 43 | * @param ProviderData $providerData the instance to load with data 44 | * @return ProviderData the given instance with properties set 45 | */ 46 | function getProviderData() 47 | { 48 | $providerData = new GithubProviderData(); 49 | 50 | $providerData->providerId = GithubProviderData::PROVIDER_ID; 51 | 52 | if (isset($this->options[self::CODE])) 53 | { 54 | $providerData->code = $this->options[self::CODE]; 55 | } 56 | else if (isset($this->options[self::ACCESS_TOKEN])) 57 | { 58 | $providerData->accessToken = $this->options[self::ACCESS_TOKEN]; 59 | } 60 | else 61 | { 62 | throw new \InvalidArgumentException('Either code or accessToken must be set for GithubProviderAccountRequest'); 63 | } 64 | 65 | return $providerData; 66 | } 67 | } -------------------------------------------------------------------------------- /src/Provider/GoogleProviderAccountRequest.php: -------------------------------------------------------------------------------- 1 | options = $options; 36 | } 37 | 38 | /** 39 | * Loads a given instance of ProviderData with the properties 40 | * stored internally in the request 41 | * 42 | * @param ProviderData $providerData the instance to load with data 43 | * @return ProviderData the given instance with properties set 44 | */ 45 | function getProviderData() 46 | { 47 | $providerData = new GoogleProviderData(); 48 | 49 | $providerData->providerId = GoogleProviderData::PROVIDER_ID; 50 | 51 | if (isset($this->options[self::CODE])) 52 | { 53 | $providerData->code = $this->options[self::CODE]; 54 | } 55 | else if (isset($this->options[self::ACCESS_TOKEN])) 56 | { 57 | $providerData->accessToken = $this->options[self::ACCESS_TOKEN]; 58 | } 59 | else 60 | { 61 | throw new \InvalidArgumentException('Either code or accessToken must be set for GoogleProviderAccountRequest'); 62 | } 63 | 64 | return $providerData; 65 | } 66 | } -------------------------------------------------------------------------------- /src/Provider/LinkedInProviderAccountRequest.php: -------------------------------------------------------------------------------- 1 | options = $options; 38 | } 39 | 40 | /** 41 | * Loads a given instance of ProviderData with the properties 42 | * stored internally in the request 43 | * 44 | * @param ProviderData $providerData the instance to load with data 45 | * @return ProviderData the given instance with properties set 46 | */ 47 | function getProviderData() 48 | { 49 | $providerData = new LinkedInProviderData(); 50 | 51 | $providerData->providerId = LinkedInProviderData::PROVIDER_ID; 52 | 53 | if (isset($this->options[self::CODE])) 54 | { 55 | $providerData->code = $this->options[self::CODE]; 56 | } 57 | else if (isset($this->options[self::ACCESS_TOKEN])) 58 | { 59 | $providerData->accessToken = $this->options[self::ACCESS_TOKEN]; 60 | } 61 | else 62 | { 63 | throw new \InvalidArgumentException('Either code or accessToken must be set for LinkedInProviderAccountRequest'); 64 | } 65 | 66 | return $providerData; 67 | } 68 | } -------------------------------------------------------------------------------- /src/Provider/ProviderAccountRequest.php: -------------------------------------------------------------------------------- 1 | ProviderData child based on the 33 | * providerId property in the $data object. 34 | * 35 | * @param $className the parent class name (should be ProviderData) 36 | * @param $data the received data object to inspect 37 | * @param array $options should contain (PropertyBasedClassNameResolver::PROPERTY_ID => ProviderData::PROVIDER_ID) entry 38 | * @return the ProviderData sub class name according to the given value for ProviderData::PROVIDER_ID 39 | */ 40 | public function resolve($className, $data, array $options = array()) 41 | { 42 | assert($className == Stormpath::PROVIDER_DATA, '$className arg should be '.Stormpath::PROVIDER_DATA); 43 | 44 | if (isset($options[DefaultClassNameResolver::PROPERTY_ID])) 45 | { 46 | $propertyId = $options[DefaultClassNameResolver::PROPERTY_ID]; 47 | 48 | $arrData = json_decode(json_encode($data), true); 49 | if (isset($arrData[$propertyId])) 50 | { 51 | $propertyValue = $arrData[$propertyId]; 52 | switch ($propertyValue) 53 | { 54 | case GoogleProviderData::PROVIDER_ID: 55 | return Stormpath::GOOGLE_PROVIDER_DATA; 56 | case FacebookProviderData::PROVIDER_ID: 57 | return Stormpath::FACEBOOK_PROVIDER_DATA; 58 | case GithubProviderData::PROVIDER_ID: 59 | return Stormpath::GITHUB_PROVIDER_DATA; 60 | case LinkedInProviderData::PROVIDER_ID: 61 | return Stormpath::LINKEDIN_PROVIDER_DATA; 62 | default: 63 | throw new \InvalidArgumentException('Could not find className for providerId '.$propertyValue); 64 | } 65 | 66 | } 67 | else 68 | { 69 | throw new \InvalidArgumentException('Property '.$propertyId.' is not defined in $data object'); 70 | } 71 | } 72 | else 73 | { 74 | throw new \InvalidArgumentException('Required key '.DefaultClassNameResolver::PROPERTY_ID.' not found in $options array'); 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /src/Resource/AccessToken.php: -------------------------------------------------------------------------------- 1 | getResourceProperty(self::ACCOUNT, Stormpath::ACCOUNT, $options); 53 | } 54 | 55 | /** 56 | * @param array $options 57 | * @return \Stormpath\Resource\Application 58 | */ 59 | public function getApplication(array $options = []) 60 | { 61 | return $this->getResourceProperty(self::APPLICATION, Stormpath::APPLICATION, $options); 62 | } 63 | 64 | /** 65 | * @return \stdClass 66 | */ 67 | public function getExpandedJwt() 68 | { 69 | return $this->getProperty(self::EXPANDED_JWT); 70 | } 71 | 72 | /** 73 | * @return string 74 | */ 75 | public function getJwt() 76 | { 77 | return $this->getProperty(self::JWT); 78 | } 79 | 80 | /** 81 | * @param array $options 82 | * @return \Stormpath\Resource\Tenant 83 | */ 84 | public function getTenant(array $options = []) 85 | { 86 | return $this->getResourceProperty(self::TENANT, Stormpath::TENANT, $options); 87 | } 88 | 89 | /** 90 | * @return null 91 | */ 92 | public function delete() 93 | { 94 | $this->getDataStore()->delete($this); 95 | } 96 | } -------------------------------------------------------------------------------- /src/Resource/AccessTokenList.php: -------------------------------------------------------------------------------- 1 | getResourceProperty(self::ACCOUNT, Stormpath::ACCOUNT, $options); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Resource/BasicLoginAttempt.php: -------------------------------------------------------------------------------- 1 | setProperty(self::TYPE, 'basic'); 32 | } 33 | 34 | // @codeCoverageIgnoreStart 35 | public function getType() 36 | { 37 | return $this->getProperty(self::TYPE); 38 | } 39 | 40 | public function getValue() 41 | { 42 | return $this->getProperty(self::VALUE); 43 | } 44 | // @codeCoverageIgnoreEnd 45 | 46 | public function setValue($value) 47 | { 48 | $this->setProperty(self::VALUE, $value); 49 | } 50 | 51 | public function getAccountStore() 52 | { 53 | $this->getProperty(self::ACCOUNT_STORE); 54 | } 55 | 56 | public function setAccountStore($accountStore) 57 | { 58 | $this->setProperty(self::ACCOUNT_STORE, $accountStore); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Resource/CustomData.php: -------------------------------------------------------------------------------- 1 | getProperty($key); 29 | } 30 | 31 | public function __set($key, $value) 32 | { 33 | $this->setProperty($key, $value); 34 | } 35 | 36 | public function save() 37 | { 38 | return $this->getDataStore()->save($this); 39 | } 40 | 41 | public function delete() 42 | { 43 | return $this->getDataStore()->delete($this); 44 | } 45 | 46 | public function remove($key) 47 | { 48 | 49 | return $this->getDataStore()->removeCustomDataItem($this, $key); 50 | 51 | } 52 | 53 | 54 | 55 | } -------------------------------------------------------------------------------- /src/Resource/Deletable.php: -------------------------------------------------------------------------------- 1 | getProperty(self::STATUS); 38 | } 39 | 40 | public function getCode() 41 | { 42 | return $this->getProperty(self::CODE); 43 | } 44 | 45 | public function getMessage() 46 | { 47 | return $this->getProperty(self::MESSAGE); 48 | } 49 | 50 | public function getDeveloperMessage() 51 | { 52 | return $this->getProperty(self::DEV_MESSAGE); 53 | } 54 | 55 | public function getMoreInfo() 56 | { 57 | return $this->getProperty(self::MORE_INFO); 58 | } 59 | 60 | public function getRequestId() 61 | { 62 | return $this->getProperty(self::REQUEST_ID); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/Resource/FacebookProvider.php: -------------------------------------------------------------------------------- 1 | setProperty(self::PROVIDER_ID, self::FACEBOOK_PROVIDER_ID); 50 | } 51 | 52 | public function getClientId() 53 | { 54 | return $this->getProperty(self::CLIENT_ID); 55 | } 56 | 57 | public function setClientId($clientId) 58 | { 59 | $this->setProperty(self::CLIENT_ID, $clientId); 60 | } 61 | 62 | public function getClientSecret() 63 | { 64 | return $this->getProperty(self::CLIENT_SECRET); 65 | } 66 | 67 | public function setClientSecret($clientSecret) 68 | { 69 | $this->setProperty(self::CLIENT_SECRET, $clientSecret); 70 | } 71 | 72 | /** 73 | * @deprecated 1.11.0.beta 74 | * @return string 75 | */ 76 | public function getRedirectUri() 77 | { 78 | return $this->getProperty(self::REDIRECT_URI); 79 | } 80 | 81 | /** 82 | * @deprecated 1.11.0.beta 83 | * @param $redirectUri 84 | */ 85 | public function setRedirectUri($redirectUri) 86 | { 87 | $this->setProperty(self::REDIRECT_URI, $redirectUri); 88 | } 89 | 90 | } -------------------------------------------------------------------------------- /src/Resource/FacebookProviderData.php: -------------------------------------------------------------------------------- 1 | getProperty(self::CODE); 32 | } 33 | 34 | public function setCode($code) 35 | { 36 | $this->setProperty(self::CODE, $code); 37 | } 38 | 39 | public function getAccessToken() 40 | { 41 | return $this->getProperty(self::ACCESS_TOKEN); 42 | } 43 | 44 | public function setAccessToken($accessToken) 45 | { 46 | $this->setProperty(self::ACCESS_TOKEN, $accessToken); 47 | } 48 | 49 | public function getRefreshToken() 50 | { 51 | return $this->getProperty(self::REFRESH_TOKEN); 52 | } 53 | 54 | public function setRefreshToken($refreshToken) 55 | { 56 | $this->setProperty(self::REFRESH_TOKEN, $refreshToken); 57 | } 58 | 59 | } -------------------------------------------------------------------------------- /src/Resource/GithubProvider.php: -------------------------------------------------------------------------------- 1 | setProperty(self::PROVIDER_ID, self::GITHUB_PROVIDER_ID); 50 | } 51 | 52 | public function getClientId() 53 | { 54 | return $this->getProperty(self::CLIENT_ID); 55 | } 56 | 57 | public function setClientId($clientId) 58 | { 59 | $this->setProperty(self::CLIENT_ID, $clientId); 60 | } 61 | 62 | public function getClientSecret() 63 | { 64 | return $this->getProperty(self::CLIENT_SECRET); 65 | } 66 | 67 | public function setClientSecret($clientSecret) 68 | { 69 | $this->setProperty(self::CLIENT_SECRET, $clientSecret); 70 | } 71 | 72 | } -------------------------------------------------------------------------------- /src/Resource/GithubProviderData.php: -------------------------------------------------------------------------------- 1 | getProperty(self::ACCESS_TOKEN); 31 | } 32 | 33 | public function setAccessToken($accessToken) 34 | { 35 | $this->setProperty(self::ACCESS_TOKEN, $accessToken); 36 | } 37 | 38 | public function getCode() 39 | { 40 | return $this->getProperty(self::CODE); 41 | } 42 | 43 | public function setCode($code) 44 | { 45 | $this->setProperty(self::CODE, $code); 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /src/Resource/GoogleProvider.php: -------------------------------------------------------------------------------- 1 | setProperty(self::PROVIDER_ID, self::GOOGLE_PROVIDER_ID); 52 | } 53 | 54 | public function getClientId() 55 | { 56 | return $this->getProperty(self::CLIENT_ID); 57 | } 58 | 59 | public function setClientId($clientId) 60 | { 61 | $this->setProperty(self::CLIENT_ID, $clientId); 62 | } 63 | 64 | public function getClientSecret() 65 | { 66 | return $this->getProperty(self::CLIENT_SECRET); 67 | } 68 | 69 | public function setClientSecret($clientSecret) 70 | { 71 | $this->setProperty(self::CLIENT_SECRET, $clientSecret); 72 | } 73 | 74 | public function getRedirectUri() 75 | { 76 | return $this->getProperty(self::REDIRECT_URI); 77 | } 78 | 79 | public function setRedirectUri($redirectUri) 80 | { 81 | $this->setProperty(self::REDIRECT_URI, $redirectUri); 82 | } 83 | } -------------------------------------------------------------------------------- /src/Resource/GoogleProviderData.php: -------------------------------------------------------------------------------- 1 | getProperty(self::CODE); 32 | } 33 | 34 | public function setCode($code) 35 | { 36 | $this->setProperty(self::CODE, $code); 37 | } 38 | 39 | public function getAccessToken() 40 | { 41 | return $this->getProperty(self::ACCESS_TOKEN); 42 | } 43 | 44 | public function setAccessToken($accessToken) 45 | { 46 | $this->setProperty(self::ACCESS_TOKEN, $accessToken); 47 | } 48 | 49 | public function getRefreshToken() 50 | { 51 | return $this->getProperty(self::REFRESH_TOKEN); 52 | } 53 | 54 | public function setRefreshToken($refreshToken) 55 | { 56 | $this->setProperty(self::REFRESH_TOKEN, $refreshToken); 57 | } 58 | 59 | } -------------------------------------------------------------------------------- /src/Resource/GrantAuthenticationToken.php: -------------------------------------------------------------------------------- 1 | getProperty(self::ACCESS_TOKEN); 36 | } 37 | 38 | public function getRefreshToken() 39 | { 40 | return $this->getProperty(self::REFRESH_TOKEN); 41 | } 42 | 43 | public function getTokenType() 44 | { 45 | return $this->getProperty(self::TOKEN_TYPE); 46 | } 47 | 48 | public function getExpiresIn() 49 | { 50 | return $this->getProperty(self::EXPIRES_IN); 51 | } 52 | 53 | public function getAccessTokenHref() 54 | { 55 | return $this->getProperty(self::ACCESS_TOKEN_HREF); 56 | } 57 | 58 | public function getAsAccessToken() 59 | { 60 | $props = new \stdClass(); 61 | $props->href = $this->getAccessTokenHref(); 62 | return $this->getDataStore()->instantiate('AccessToken', $props); 63 | } 64 | 65 | public function getAsRefreshToken() 66 | { 67 | $props = new \stdClass(); 68 | $props->href = $this->getAccessTokenHref(); 69 | return $this->getDataStore()->instantiate('RefreshToken', $props); 70 | } 71 | 72 | 73 | } -------------------------------------------------------------------------------- /src/Resource/GroupList.php: -------------------------------------------------------------------------------- 1 | getAccount(), $groupMembership->getGroup(), Client::getInstance()->getDataStore(), $options); 52 | } 53 | 54 | public function getAccount(array $options = array()) 55 | { 56 | return $this->getResourceProperty(self::ACCOUNT, Stormpath::ACCOUNT, $options); 57 | } 58 | 59 | public function getGroup(array $options = array()) 60 | { 61 | return $this->getResourceProperty(self::GROUP, Stormpath::GROUP, $options); 62 | } 63 | 64 | public function setAccount(Account $account) 65 | { 66 | $this->setResourceProperty(self::ACCOUNT, $account); 67 | } 68 | 69 | public function setGroup(Group $group) 70 | { 71 | $this->setResourceProperty(self::GROUP, $group); 72 | } 73 | 74 | public function delete() 75 | { 76 | $this->getDataStore()->delete($this); 77 | } 78 | 79 | /** 80 | * THIS IS NOT PART OF THE STORMPATH PUBLIC API. SDK end-users should not call it - it could be removed or 81 | * changed at any time. It has the public modifier only as an implementation technique to be accessible to other 82 | * resource implementations. 83 | * 84 | * @param $account the account to associate with the group. 85 | * @param $group the group which will contain the account. 86 | * @param $dataStore the datastore used to create the membership. 87 | * @param $options the options to pass to the group membership creation. 88 | * @return the created GroupMembership instance. 89 | */ 90 | public static function _create(Account $account, Group $group, InternalDataStore $dataStore, array $options = array()) 91 | { 92 | //TODO: enable auto discovery 93 | $href = '/' .self::PATH; 94 | 95 | $groupMembership = $dataStore->instantiate(Stormpath::GROUP_MEMBERSHIP); 96 | $groupMembership->setResourceProperty(self::ACCOUNT, $account); 97 | $groupMembership->setResourceProperty(self::GROUP, $group); 98 | 99 | return $dataStore->create($href, $groupMembership, Stormpath::GROUP_MEMBERSHIP, $options); 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /src/Resource/GroupMembershipList.php: -------------------------------------------------------------------------------- 1 | getDataStore()->save($this); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/Resource/LinkedInProvider.php: -------------------------------------------------------------------------------- 1 | setProperty(self::PROVIDER_ID, self::LINKEDIN_PROVIDER_ID); 51 | } 52 | 53 | public function getClientId() 54 | { 55 | return $this->getProperty(self::CLIENT_ID); 56 | } 57 | 58 | public function setClientId($clientId) 59 | { 60 | $this->setProperty(self::CLIENT_ID, $clientId); 61 | } 62 | 63 | public function getClientSecret() 64 | { 65 | return $this->getProperty(self::CLIENT_SECRET); 66 | } 67 | 68 | public function setClientSecret($clientSecret) 69 | { 70 | $this->setProperty(self::CLIENT_SECRET, $clientSecret); 71 | } 72 | 73 | public function getRedirectUri() 74 | { 75 | return $this->getProperty(self::REDIRECT_URI); 76 | } 77 | 78 | public function setRedirectUri($redirectUri) 79 | { 80 | $this->setProperty(self::REDIRECT_URI, $redirectUri); 81 | } 82 | } -------------------------------------------------------------------------------- /src/Resource/LinkedInProviderData.php: -------------------------------------------------------------------------------- 1 | getProperty(self::ACCESS_TOKEN); 31 | } 32 | 33 | public function setAccessToken($accessToken) 34 | { 35 | $this->setProperty(self::ACCESS_TOKEN, $accessToken); 36 | } 37 | 38 | public function getCode() 39 | { 40 | return $this->getProperty(self::CODE); 41 | } 42 | 43 | public function setCode($code) 44 | { 45 | $this->setProperty(self::CODE, $code); 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /src/Resource/OauthPolicy.php: -------------------------------------------------------------------------------- 1 | getProperty(self::ACCESS_TOKEN_TTL); 54 | } 55 | 56 | /** 57 | * @param $ttl 58 | */ 59 | public function setAccessTokenTtl($ttl) 60 | { 61 | $this->setProperty(self::ACCESS_TOKEN_TTL, $ttl); 62 | } 63 | 64 | /** 65 | * @return string 66 | */ 67 | public function getRefreshTokenTtl() 68 | { 69 | return $this->getProperty(self::REFRESH_TOKEN_TTL); 70 | } 71 | 72 | /** 73 | * @param $ttl 74 | */ 75 | public function setRefreshTokenTtl($ttl) 76 | { 77 | $this->setProperty(self::REFRESH_TOKEN_TTL, $ttl); 78 | } 79 | 80 | /** 81 | * @return null 82 | */ 83 | public function getTokenEndpoint() 84 | { 85 | return $this->getProperty(self::TOKEN_ENDPOINT); 86 | } 87 | 88 | } -------------------------------------------------------------------------------- /src/Resource/OrganizationList.php: -------------------------------------------------------------------------------- 1 | items = $items; 34 | $this->limit = $limit; 35 | $this->offset = $offset; 36 | } 37 | 38 | public function getItems() 39 | { 40 | return $this->items; 41 | } 42 | 43 | public function getLimit() 44 | { 45 | return $this->limit; 46 | } 47 | 48 | public function getOffset() 49 | { 50 | return $this->offset; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/Resource/PasswordResetToken.php: -------------------------------------------------------------------------------- 1 | getProperty(self::EMAIL); 34 | } 35 | // @codeCoverageIgnoreEnd 36 | 37 | public function setEmail($email) 38 | { 39 | $this->setProperty(self::EMAIL, $email); 40 | } 41 | 42 | public function getAccount(array $options = array()) 43 | { 44 | return $this->getResourceProperty(self::ACCOUNT, Stormpath::ACCOUNT, $options); 45 | } 46 | 47 | public function setAccountStore($accountStore) 48 | { 49 | $this->setProperty(self::ACCOUNT_STORE, $accountStore); 50 | } 51 | 52 | public function setPassword($password) 53 | { 54 | $this->setProperty(self::PASSWORD, $password); 55 | } 56 | 57 | public function getPassword() 58 | { 59 | $this->getProperty(self::PASSWORD); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/Resource/Provider.php: -------------------------------------------------------------------------------- 1 | getProperty(self::CREATED_AT); 37 | } 38 | 39 | /** 40 | * Returns the provider's last modification date 41 | * 42 | * @return the provider's last modification date 43 | */ 44 | public function getModifiedAt() 45 | { 46 | return $this->getProperty(self::MODIFIED_AT); 47 | } 48 | 49 | /** 50 | * Getter for the Stormpath ID of the Provider (e.g. "facebook" or "google"). 51 | * 52 | * @return the Stormpath ID of the Provider. 53 | */ 54 | public function getProviderId() 55 | { 56 | return $this->getProperty(self::PROVIDER_ID); 57 | } 58 | } -------------------------------------------------------------------------------- /src/Resource/ProviderAccountAccess.php: -------------------------------------------------------------------------------- 1 | getProperty(self::PROVIDER_DATA); 28 | } 29 | 30 | public function setProviderData($providerData) 31 | { 32 | $this->setProperty(self::PROVIDER_DATA, $providerData); 33 | } 34 | } -------------------------------------------------------------------------------- /src/Resource/ProviderAccountResult.php: -------------------------------------------------------------------------------- 1 | setProperty(self::NEW_ACCOUNT, $properties->newAccount); 35 | unset($properties->newAccount); 36 | $account = $this->getDataStore()->instantiate(Stormpath::ACCOUNT, $properties); 37 | $this->setProperty(self::ACCOUNT, $account); 38 | } 39 | } 40 | 41 | public function getAccount(array $options = array()) 42 | { 43 | return $this->getProperty(self::ACCOUNT); 44 | } 45 | 46 | public function isNewAccount() 47 | { 48 | return $this->getProperty(self::NEW_ACCOUNT); 49 | } 50 | 51 | } -------------------------------------------------------------------------------- /src/Resource/ProviderData.php: -------------------------------------------------------------------------------- 1 | getProperty(self::PROVIDER_ID); 32 | } 33 | 34 | public function setProviderId($providerId) 35 | { 36 | $this->setProperty(self::PROVIDER_ID, $providerId); 37 | } 38 | 39 | public function getCreatedAt() 40 | { 41 | return $this->getProperty(self::CREATED_AT); 42 | } 43 | 44 | public function setCreatedAt($createdAt) 45 | { 46 | $this->setProperty(self::CREATED_AT, $createdAt); 47 | } 48 | 49 | public function getModifiedAt() 50 | { 51 | return $this->getProperty(self::CREATED_AT); 52 | } 53 | 54 | public function setModifiedAt($modifiedAt) 55 | { 56 | $this->setProperty(self::CREATED_AT, $modifiedAt); 57 | } 58 | } -------------------------------------------------------------------------------- /src/Resource/RefreshToken.php: -------------------------------------------------------------------------------- 1 | getMessage()) ? $error->getMessage() : '', $error->getCode()); 28 | $this->error = $error; 29 | } 30 | 31 | public function getStatus() 32 | { 33 | return $this->error ? $this->error->getStatus() : -1; 34 | } 35 | 36 | public function getErrorCode() 37 | { 38 | return $this->error ? $this->error->getCode() : -1; 39 | } 40 | 41 | public function getDeveloperMessage() 42 | { 43 | return $this->error ? $this->error->getDeveloperMessage() : null; 44 | } 45 | 46 | public function getMoreInfo() 47 | { 48 | return $this->error ? $this->error->getMoreInfo() : null; 49 | } 50 | 51 | public function getRequestId() 52 | { 53 | return $this->error ? $this->error->getRequestId() : null; 54 | } 55 | } -------------------------------------------------------------------------------- /src/Resource/SamlProviderData.php: -------------------------------------------------------------------------------- 1 | getProperty(self::ENTITY_ID); 39 | } 40 | 41 | /** 42 | * The certificate that is used to sign the requests sent to the IdP. If 43 | * you retrieve XML, the certificate will be embedded. If you retrieve 44 | * JSON, you’ll have to follow a further /x509certificates link to 45 | * retrieve it. 46 | * 47 | * @since 1.13.0 48 | * @param array $options 49 | * @return null|\Stormpath\Resource\X509SigningCert 50 | */ 51 | public function getX509SigningCert(array $options = []) 52 | { 53 | return $this->getResourceProperty(self::X509_SIGNING_CERT, Stormpath::X509_SIGNING_CERT, $options); 54 | } 55 | 56 | /** 57 | * This is the location the IdP will send its response to. 58 | * 59 | * @since 1.13.0 60 | * @param array $options 61 | * @return null|\Stormpath\Resource\AssertionConsumerServicePostEndpoint 62 | */ 63 | public function getAssertionConsumerServicePostEndpoint(array $options = []) 64 | { 65 | return $this->getResourceProperty(self::ASSERTION_CONSUMER_SERVICE_POST_ENDPOINT, Stormpath::ASSERTION_CONSUMER_SERVICE_POST_ENDPOINT); 66 | } 67 | } -------------------------------------------------------------------------------- /src/Resource/Saveable.php: -------------------------------------------------------------------------------- 1 | getProperty(self::LOGIN); 34 | } 35 | 36 | public function setLogin($login) 37 | { 38 | $this->setProperty(self::LOGIN, $login); 39 | } 40 | 41 | public function getAccountStore($options = array()) 42 | { 43 | return $this->getResourceProperty(self::ACCOUNT_STORE, Stormpath::ACCOUNT_STORE, $options); 44 | } 45 | 46 | public function setAccountStore(AccountStore $accountStore) 47 | { 48 | $this->setResourceProperty(self::ACCOUNT_STORE, $accountStore); 49 | } 50 | 51 | 52 | } -------------------------------------------------------------------------------- /src/Resource/X509SigningCert.php: -------------------------------------------------------------------------------- 1 | name = $name; 43 | $this->nameFormat = $nameFormat; 44 | $this->accountAttributes = $accountAttributes; 45 | } 46 | 47 | /** 48 | * Returns the SAML Attribute name, that when encountered, should have its value applied as Account field values. 49 | * When this name is encountered when processing a SAML Attribute Statement, its associated value will be set as the 50 | * value for all Stormpath Account field names specified in the 51 | * accountAttributes collection. 52 | * 53 | * @since 1.13.0 54 | * @return string SAML Attribute name, should have its value set on the specified Account fields. 55 | */ 56 | public function getName() 57 | { 58 | return $this->name; 59 | } 60 | 61 | 62 | /** 63 | * Returns the format for the SAML Attribute. 64 | * 65 | * @since 1.13.0 66 | * @return string SAML format for the SAML Attribute. 67 | */ 68 | public function getNameFormat() 69 | { 70 | return $this->nameFormat; 71 | } 72 | 73 | /** 74 | * Returns the Stormpath account fields that should be updated for the 75 | * SAML Attribute name. If discovered, that SAML Attribute value will 76 | * be set on all of the Stormpath account fields named in this array. 77 | * 78 | * @since 1.13.0 79 | * @return array Stormpath account fields that should be updated. 80 | */ 81 | public function getAccountAttributes() 82 | { 83 | return $this->accountAttributes; 84 | } 85 | 86 | /** 87 | * Prevents setting random values on the class. We only need name, nameFormat, and accountAttributes 88 | * 89 | * @since 1.13.0 90 | * @param $attribute 91 | * @param $value 92 | * @throws \BadMethodCallException 93 | */ 94 | public function __set($attribute, $value) 95 | { 96 | throw new \BadMethodCallException('You can not set properties directly on this class. Please use the Builder'); 97 | } 98 | 99 | 100 | } -------------------------------------------------------------------------------- /src/Saml/AttributeStatementMappingRuleBuilder.php: -------------------------------------------------------------------------------- 1 | name = $name; 43 | return $this; 44 | } 45 | 46 | /** 47 | * Sets the format for the SAML Attribute. 48 | * Examples of valid formats are: 49 | * urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress 50 | * urn:oasis:names:tc:SAML:2.0:nameid-format:persistent 51 | * urn:oasis:names:tc:SAML:2.0:nameid-format:transient 52 | * urn:oasis:names:tc:SAML:2.0:attrname-format:basic 53 | * urn:oasis:names:tc:SAML:2.0:nameid-format:entity 54 | * 55 | * @since 1.13.0 56 | * @param string $nameFormat 57 | * @return self 58 | */ 59 | public function setNameFormat($nameFormat) 60 | { 61 | $this->nameFormat = $nameFormat; 62 | return $this; 63 | } 64 | 65 | /** 66 | * Sets the Stormpath account fields that should be updated when encountering 67 | * SAML Attribute name. If discovered, that SAML Attribute value will be 68 | * set on all of the Stormpath account fields named in this collection. 69 | * 70 | * @since 1.13.0 71 | * @param array $accountAttributes 72 | * @return self 73 | */ 74 | public function setAccountAttributes(array $accountAttributes) 75 | { 76 | $this->accountAttributes = $accountAttributes; 77 | return $this; 78 | } 79 | 80 | /** 81 | * Builds a new AttributeStatementMappingRule based on the current state of this builder. 82 | * 83 | * @since 1.13.0 84 | * @return AttributeStatementMappingRule a new AttributeStatementMappingRule to be included in the AttributeStatementMappingRules for a Saml Provider. 85 | */ 86 | public function build() 87 | { 88 | return new AttributeStatementMappingRule($this->name, $this->nameFormat, $this->accountAttributes); 89 | } 90 | 91 | } -------------------------------------------------------------------------------- /src/Saml/AttributeStatementMappingRules.php: -------------------------------------------------------------------------------- 1 | getProperty(self::ITEMS); 40 | } 41 | 42 | /** 43 | * Specifies the Set of all AttributeStatementMappingRule objectss that indicate how 44 | * SAML Attribute Statements should populate one or more Stormpath Account field 45 | * values after a successful SAML login. 46 | * 47 | * @since 1.13.0 48 | * @param array $items an array of AttributeStatementMappingRule objects to build a SAML provider. 49 | * @return self 50 | */ 51 | public function setItems(array $items) 52 | { 53 | $this->setProperty(self::ITEMS, $items); 54 | return $this; 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /src/Saml/AttributeStatementMappingRulesBuilder.php: -------------------------------------------------------------------------------- 1 | addAttributeStatementMappingRule($mappingRule); 44 | } 45 | 46 | return $this; 47 | } 48 | 49 | /** 50 | * Adds a new AttributeStatementMappingRule to the array of AttributeStatementMappingRule objects, 51 | * indicating how a SAML Attribute Statement should populate one or more Stormpath Account 52 | * field values after a successful SAML login. 53 | * 54 | * @since 1.13.0 55 | * @param AttributeStatementMappingRule $attributeStatementMappingRule an instance of 56 | * AttributeStatementMappingRule 57 | * to be added to array of objects 58 | * @return AttributeStatementMappingRulesBuilder 59 | */ 60 | public function addAttributeStatementMappingRule(AttributeStatementMappingRule $attributeStatementMappingRule) 61 | { 62 | $this->attributeStatementMappingRules[] = $attributeStatementMappingRule; 63 | return $this; 64 | } 65 | 66 | /** 67 | * Builds a new AttributeStatementMappingRules instance based on the state of this builder. 68 | * 69 | * @return \Stormpath\Saml\AttributeStatementMappingRules 70 | */ 71 | public function build() 72 | { 73 | $this->attributeStatementMappingRules = array_unique($this->attributeStatementMappingRules, SORT_REGULAR); 74 | 75 | $rules = new \Stormpath\Saml\AttributeStatementMappingRules(); 76 | $rules->setItems($this->attributeStatementMappingRules); 77 | return $rules; 78 | } 79 | } -------------------------------------------------------------------------------- /src/Util/Magic.php: -------------------------------------------------------------------------------- 1 | methods = array_flip(get_class_methods(get_class($this))); 29 | } 30 | 31 | /** 32 | * Magic "get" method 33 | * 34 | * @param string $property Property name 35 | * @return mixed|null Property value if it exists, null if not 36 | */ 37 | public function __get($property) 38 | { 39 | $method = 'get' .ucfirst($property); 40 | if (isset($this->methods[$method])) { 41 | return $this->{$method}(); 42 | } 43 | 44 | return null; 45 | } 46 | 47 | /** 48 | * Magic "set" method 49 | * 50 | * @param string $property Property name 51 | * @param mixed $value Property value 52 | */ 53 | public function __set($property, $value) 54 | { 55 | $method = 'set' .ucfirst($property); 56 | if (isset($this->methods[$method])) { 57 | $this->{$method}($value); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /src/Util/NonceStore.php: -------------------------------------------------------------------------------- 1 | pool = $dataStore->getCachePool(); 36 | } 37 | 38 | public function getNonce($nonce) 39 | { 40 | $item = $this->pool->getItem('nonce_'.$nonce); 41 | return $item->get(); 42 | } 43 | 44 | public function putNonce($nonce) 45 | { 46 | $item = $this->pool->getItem('nonce_'.$nonce); 47 | $item->set($nonce); 48 | $item->expiresAfter(60); 49 | $this->pool->save($item); 50 | } 51 | // @codeCoverageIgnoreStart 52 | } 53 | -------------------------------------------------------------------------------- /src/Util/RequestUtils.php: -------------------------------------------------------------------------------- 1 | true if the specified parsed url (array result of a call to parse_url(url)) 28 | * uses a standard port (i.e. http == 80 or https == 443), 29 | * false otherwise. 30 | * 31 | * @param $parsedUrl 32 | * @return true if the specified parsed url is using a non-standard port, false otherwise 33 | */ 34 | public static function isDefaultPort(UriInterface $uri) 35 | { 36 | $scheme = strtolower($uri->getScheme()); 37 | $port = $uri->getPort() ?: $scheme == 'https' ? 443 : 0; 38 | return $port <= 0 or ($port == 80 and $scheme == 'http') or ($port == 443 and $scheme == 'https'); 39 | } 40 | 41 | public static function encodeUrl($value, $path, $canonical) 42 | { 43 | if (is_numeric($value)) 44 | { 45 | return strval($value); 46 | } 47 | 48 | $encoded = urlencode($value); 49 | 50 | if ($canonical) 51 | { 52 | $encoded = strtr( 53 | strtr( 54 | strtr($encoded, 55 | array('+' => '%20')), 56 | array('*' =>'%2A')), 57 | array('%7E' => '~')); 58 | 59 | if ($path) 60 | { 61 | $encoded = strtr($encoded, array('%2F' => '/')); 62 | } 63 | } 64 | 65 | return $encoded; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/Util/UserAgentBuilder.php: -------------------------------------------------------------------------------- 1 | phpVersion = $version; 53 | return $this; 54 | } 55 | 56 | /** 57 | * Set the Operating System Name 58 | * @param $os 59 | * @return $this 60 | */ 61 | public function setOsName($os) 62 | { 63 | $this->osName = $os; 64 | return $this; 65 | } 66 | 67 | /** 68 | * Set the Operating System Version 69 | * @param $version 70 | * @return $this 71 | */ 72 | public function setOsVersion($version) 73 | { 74 | $this->osVersion = $version; 75 | return $this; 76 | } 77 | 78 | /** 79 | * Build your User Agent. This will build in an order required by Stormpath. 80 | * @return string 81 | * @throws UserAgentException 82 | */ 83 | public function build() 84 | { 85 | $this->validateUserAgentProperties(); 86 | 87 | $userAgent = array(); 88 | 89 | 90 | if(\Stormpath\Client::$integration) { 91 | $userAgent[] = \Stormpath\Client::$integration; 92 | } 93 | $userAgent[] = 'stormpath-sdk-php/'. Version::SDK_VERSION; 94 | $userAgent[] = 'php/' . $this->phpVersion; 95 | $userAgent[] = $this->osName .'/'. $this->osVersion; 96 | 97 | return implode(' ', $userAgent); 98 | 99 | } 100 | 101 | private function validateUserAgentProperties() 102 | { 103 | if(!$this->phpVersion) throw new \InvalidArgumentException('Please provide a PHP Version.'); 104 | if(!$this->osName) throw new \InvalidArgumentException('Please provide an Operating System Name.'); 105 | if(!$this->osVersion) throw new \InvalidArgumentException('Please provide an Operating System Version.'); 106 | } 107 | 108 | 109 | 110 | } -------------------------------------------------------------------------------- /src/Util/Version.php: -------------------------------------------------------------------------------- 1 |