1<?php
2/*
3 * Copyright 2012 Google Inc.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/**
19 * Credentials object used for OAuth 2.0 Signed JWT assertion grants.
20 *
21 * @author Chirag Shah <chirags@google.com>
22 */
23class Google_AssertionCredentials {
24  const MAX_TOKEN_LIFETIME_SECS = 3600;
25
26  public $serviceAccountName;
27  public $scopes;
28  public $privateKey;
29  public $privateKeyPassword;
30  public $assertionType;
31  public $sub;
32  /**
33   * @deprecated
34   * @link http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-06
35   */
36  public $prn;
37
38  /**
39   * @param $serviceAccountName
40   * @param $scopes array List of scopes
41   * @param $privateKey
42   * @param string $privateKeyPassword
43   * @param string $assertionType
44   * @param bool|string $sub The email address of the user for which the
45   *               application is requesting delegated access.
46   */
47  public function __construct(
48      $serviceAccountName,
49      $scopes,
50      $privateKey,
51      $privateKeyPassword = 'notasecret',
52      $assertionType = 'http://oauth.net/grant_type/jwt/1.0/bearer',
53      $sub = false) {
54    $this->serviceAccountName = $serviceAccountName;
55    $this->scopes = is_string($scopes) ? $scopes : implode(' ', $scopes);
56    $this->privateKey = $privateKey;
57    $this->privateKeyPassword = $privateKeyPassword;
58    $this->assertionType = $assertionType;
59    $this->sub = $sub;
60    $this->prn = $sub;
61  }
62
63  public function generateAssertion() {
64    $now = time();
65
66    $jwtParams = array(
67          'aud' => Google_OAuth2::OAUTH2_TOKEN_URI,
68          'scope' => $this->scopes,
69          'iat' => $now,
70          'exp' => $now + self::MAX_TOKEN_LIFETIME_SECS,
71          'iss' => $this->serviceAccountName,
72    );
73
74    if ($this->sub !== false) {
75      $jwtParams['sub'] = $this->sub;
76    } else if ($this->prn !== false) {
77      $jwtParams['prn'] = $this->prn;
78    }
79
80    return $this->makeSignedJwt($jwtParams);
81  }
82
83  /**
84   * Creates a signed JWT.
85   * @param array $payload
86   * @return string The signed JWT.
87   */
88  private function makeSignedJwt($payload) {
89    $header = array('typ' => 'JWT', 'alg' => 'RS256');
90
91    $segments = array(
92      Google_Utils::urlSafeB64Encode(json_encode($header)),
93      Google_Utils::urlSafeB64Encode(json_encode($payload))
94    );
95
96    $signingInput = implode('.', $segments);
97    $signer = new Google_P12Signer($this->privateKey, $this->privateKeyPassword);
98    $signature = $signer->sign($signingInput);
99    $segments[] = Google_Utils::urlSafeB64Encode($signature);
100
101    return implode(".", $segments);
102  }
103}
104