1<?php
2/**
3 * Copyright 2017 Facebook, Inc.
4 *
5 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6 * use, copy, modify, and distribute this software in source code or binary
7 * form for use in connection with the web services and APIs provided by
8 * Facebook.
9 *
10 * As with any software that integrates with the Facebook platform, your use
11 * of this software is subject to the Facebook Developer Principles and
12 * Policies [http://developers.facebook.com/policy/]. This copyright notice
13 * shall be included in all copies or substantial portions of the software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 */
24namespace Facebook\Helpers;
25
26use Facebook\Facebook;
27use Facebook\FacebookApp;
28use Facebook\FacebookClient;
29use Facebook\SignedRequest;
30use Facebook\Authentication\AccessToken;
31use Facebook\Authentication\OAuth2Client;
32
33/**
34 * Class FacebookSignedRequestFromInputHelper
35 *
36 * @package Facebook
37 */
38abstract class FacebookSignedRequestFromInputHelper
39{
40    /**
41     * @var SignedRequest|null The SignedRequest entity.
42     */
43    protected $signedRequest;
44
45    /**
46     * @var FacebookApp The FacebookApp entity.
47     */
48    protected $app;
49
50    /**
51     * @var OAuth2Client The OAuth 2.0 client service.
52     */
53    protected $oAuth2Client;
54
55    /**
56     * Initialize the helper and process available signed request data.
57     *
58     * @param FacebookApp    $app          The FacebookApp entity.
59     * @param FacebookClient $client       The client to make HTTP requests.
60     * @param string|null    $graphVersion The version of Graph to use.
61     */
62    public function __construct(FacebookApp $app, FacebookClient $client, $graphVersion = null)
63    {
64        $this->app = $app;
65        $graphVersion = $graphVersion ?: Facebook::DEFAULT_GRAPH_VERSION;
66        $this->oAuth2Client = new OAuth2Client($this->app, $client, $graphVersion);
67
68        $this->instantiateSignedRequest();
69    }
70
71    /**
72     * Instantiates a new SignedRequest entity.
73     *
74     * @param string|null
75     */
76    public function instantiateSignedRequest($rawSignedRequest = null)
77    {
78        $rawSignedRequest = $rawSignedRequest ?: $this->getRawSignedRequest();
79
80        if (!$rawSignedRequest) {
81            return;
82        }
83
84        $this->signedRequest = new SignedRequest($this->app, $rawSignedRequest);
85    }
86
87    /**
88     * Returns an AccessToken entity from the signed request.
89     *
90     * @return AccessToken|null
91     *
92     * @throws \Facebook\Exceptions\FacebookSDKException
93     */
94    public function getAccessToken()
95    {
96        if ($this->signedRequest && $this->signedRequest->hasOAuthData()) {
97            $code = $this->signedRequest->get('code');
98            $accessToken = $this->signedRequest->get('oauth_token');
99
100            if ($code && !$accessToken) {
101                return $this->oAuth2Client->getAccessTokenFromCode($code);
102            }
103
104            $expiresAt = $this->signedRequest->get('expires', 0);
105
106            return new AccessToken($accessToken, $expiresAt);
107        }
108
109        return null;
110    }
111
112    /**
113     * Returns the SignedRequest entity.
114     *
115     * @return SignedRequest|null
116     */
117    public function getSignedRequest()
118    {
119        return $this->signedRequest;
120    }
121
122    /**
123     * Returns the user_id if available.
124     *
125     * @return string|null
126     */
127    public function getUserId()
128    {
129        return $this->signedRequest ? $this->signedRequest->getUserId() : null;
130    }
131
132    /**
133     * Get raw signed request from input.
134     *
135     * @return string|null
136     */
137    abstract public function getRawSignedRequest();
138
139    /**
140     * Get raw signed request from POST input.
141     *
142     * @return string|null
143     */
144    public function getRawSignedRequestFromPost()
145    {
146        if (isset($_POST['signed_request'])) {
147            return $_POST['signed_request'];
148        }
149
150        return null;
151    }
152
153    /**
154     * Get raw signed request from cookie set from the Javascript SDK.
155     *
156     * @return string|null
157     */
158    public function getRawSignedRequestFromCookie()
159    {
160        if (isset($_COOKIE['fbsr_' . $this->app->getId()])) {
161            return $_COOKIE['fbsr_' . $this->app->getId()];
162        }
163
164        return null;
165    }
166}
167