Issues (69)

src/ApiAuth.php (3 issues)

Labels
1
<?php
2
3
4
namespace ArcherZdip\LaravelApiAuth;
5
6
use Exception;
7
use Carbon\Carbon;
0 ignored issues
show
The type Carbon\Carbon was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
8
use ArcherZdip\LaravelApiAuth\Models\AppClient;
9
use function ArcherZdip\LaravelApiAuth\Helper\base64_urlsafe_decode;
10
use function ArcherZdip\LaravelApiAuth\Helper\base64_urlsafe_encode;
11
12
class ApiAuth
13
{
14
    /**
15
     * @var string $token
16
     */
17
    protected $token;
18
19
    /**
20
     * @var array $validKeys
21
     */
22
    protected $validKeys = ['appid', 'token', 'exp'];
23
24
    public function __construct(string $token)
25
    {
26
        $this->token = $token;
27
28
        $this->verifySign();
29
    }
30
31
    /**
32
     * Check token is valid
33
     *
34
     * @param string $token
35
     * @return bool
36
     */
37
    public static function isValid(string $token): bool
38
    {
39
        try {
40
            new static($token);
41
            return true;
42
        } catch (Exception $exception) {
43
            return false;
44
        }
45
    }
46
47
    /**
48
     * Get Appid by token
49
     *
50
     * @param string $token
51
     * @return string
52
     */
53
    public static function getAppId(string $token): string
54
    {
55
        return explode('.', base64_urlsafe_decode($token))[0] ?? '';
56
    }
57
58
    /**
59
     * Generate token, for test token is valid
60
     *
61
     * @param string $appid
62
     * @param int|null $exp
63
     * @return string
64
     * @throws Exception
65
     */
66
    public static function generateToken(string $appid, int $exp = null): string
67
    {
68
        if ($exp === null) {
69
            $exp = time();
70
        }
71
72
        $appClient = AppClient::getSecretByAppId($appid);
73
        if (!$appClient) {
74
            throw new Exception("The AppId is not exists");
75
        }
76
        $secret = $appClient->secret;
77
        $sign = sha1($appid . $secret . $exp);
78
79
        return base64_urlsafe_encode(implode('.', [$appid, $sign, $exp]));
80
    }
81
82
    /**
83
     * Check appid
84
     *
85
     * @param string $appid
86
     * @return AppClient $appClient
87
     * @throws Exception
88
     */
89
    protected function checkAppId(string $appid): ?AppClient
90
    {
91
        $appClient = AppClient::getSecretByAppId($appid);
92
        if (!$appClient) {
93
            throw new Exception("The AppId is not exists");
94
        }
95
96
        return $appClient;
97
    }
98
99
    /**
100
     * verify sign
101
     *
102
     * @return null
103
     * @throws Exception
104
     */
105
    protected function verifySign()
106
    {
107
        [$appid, $sign, $exp] = $this->tokenDecode($this->token);
108
109
        // check timeout
110
        $now = Carbon::now()->timestamp;
111
        $tokenTimeout = (int)config('apikey.token_timeout', 0);
0 ignored issues
show
The function config was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

111
        $tokenTimeout = (int)/** @scrutinizer ignore-call */ config('apikey.token_timeout', 0);
Loading history...
112
        if ($tokenTimeout !== 0 && $exp + $tokenTimeout > $now) {
113
            throw new Exception('Token is timeout.');
114
        }
115
116
        if ($this->createSign($appid, $exp) !== $sign) {
0 ignored issues
show
$exp of type string is incompatible with the type integer expected by parameter $exp of ArcherZdip\LaravelApiAuth\ApiAuth::createSign(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

116
        if ($this->createSign($appid, /** @scrutinizer ignore-type */ $exp) !== $sign) {
Loading history...
117
            throw new Exception('Token is error.');
118
        }
119
120
        return null;
121
    }
122
123
    /**
124
     * create sign
125
     *
126
     * @param string $appid
127
     * @param int $exp
128
     * @return string
129
     * @throws Exception
130
     */
131
    protected function createSign(string $appid, int $exp): string
132
    {
133
        $secret = $this->checkAppId($appid)->secret;
134
        return sha1($appid . $secret . (string)$exp);
135
    }
136
137
    /**
138
     * Token decode
139
     *
140
     * @param string $token
141
     * @return array|null
142
     * @throws Exception
143
     */
144
    protected function tokenDecode(string $token): ?array
145
    {
146
        $data = explode('.', base64_urlsafe_decode($token));
147
        if (count($this->validKeys) !== count($data)) {
148
            throw new Exception('token invalid');
149
        }
150
151
        return $data;
152
    }
153
}