robots.txt
[anoweco.git] / www / auth.php
1 <?php
2 namespace anoweco;
3 /**
4  * IndieAuth endpoint
5  *
6  * @author Christian Weiske <cweiske@cweiske.de>
7  */
8 header('HTTP/1.0 500 Internal Server Error');
9 require 'www-header.php';
10
11 function getOrCreateUser($mode, $name, $imageurl, $email)
12 {
13     if ($mode == 'anonymous') {
14         $name     = 'Anonymous';
15         $email    = '';
16         $imageurl = '';
17     } else {
18         if ($name == '') {
19             $name = 'Anonymous';
20         }
21     }
22     if ($imageurl == '') {
23         $imageurl = getImageUrl($email);
24     }
25
26     $storage = new Storage();
27     $id = $storage->findUser($name, $imageurl);
28     if ($id !== null) {
29         return $id;
30     }
31     $id = $storage->createUser($name, $imageurl);
32     return $id;
33 }
34
35 function getImageUrl($email)
36 {
37     //FIXME: libravatar
38     return Urls::userImg((object)['user_imageurl' => '']);
39 }
40
41 header('IndieAuth: authorization_endpoint');
42 if ($_SERVER['REQUEST_METHOD'] == 'GET') {
43     if (count($_GET) == 0) {
44         //no parameters - show the index page
45         header('HTTP/1.0 200 OK');
46         header('Content-Type: text/html');
47         render('auth-index', ['baseurl' => Urls::full('/')]);
48         exit();
49     }
50
51     $me            = verifyUrlParameter($_GET, 'me');
52     $redirect_uri  = verifyUrlParameter($_GET, 'redirect_uri');
53     $client_id     = verifyUrlParameter($_GET, 'client_id');
54     $state         = getOptionalParameter($_GET, 'state', null);
55     $response_type = getOptionalParameter($_GET, 'response_type', 'id');
56     $scope         = getOptionalParameter($_GET, 'scope', null);
57
58     $id = array(
59         'mode'     => 'anonymous',
60         'name'     => '',
61         'imageurl' => '',
62     );
63     $userbaseurl = Urls::full('/user/');
64     if (substr($me, 0, strlen($userbaseurl)) == $userbaseurl) {
65         //actual user URL - loads his data
66         $userid = substr($me, strrpos($me, '/') + 1, -4);
67         if (intval($userid) == $userid) {
68             $storage = new Storage();
69             $rowUser = $storage->getUser($userid);
70             if ($rowUser !== null) {
71                 $id['mode']     = 'data';
72                 $id['name']     = $rowUser->user_name;
73                 $id['imageurl'] = $rowUser->user_imageurl;
74                 if ($id['imageurl'] == Urls::userImg()) {
75                     $id['imageurl'] = '';
76                 }
77             }
78         }
79     }
80
81     //let the user choose his identity
82     header('HTTP/1.0 200 OK');
83     render(
84         'auth-choose',
85         array(
86             'auth' => array(
87                 'redirect_uri'  => $redirect_uri,
88                 'client_id'     => $client_id,
89                 'state'         => $state,
90                 'response_type' => $response_type,
91                 'scope'         => $scope,
92             ),
93             'id' => $id,
94             'formaction' => '/auth.php?action=login',
95         )
96     );
97     exit();
98 } else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
99     if (isset($_GET['action']) && $_GET['action'] == 'login') {
100         //log the user in
101         $auth = $_POST['auth'];
102         $redirect_uri  = verifyUrlParameter($auth, 'redirect_uri');
103         $client_id     = verifyUrlParameter($auth, 'client_id');
104         $state         = getOptionalParameter($auth, 'state', null);
105         $response_type = getOptionalParameter($auth, 'response_type', 'id');
106         $scope         = getOptionalParameter($auth, 'scope', null);
107
108         $id = $_POST['id'];
109         verifyParameter($id, 'mode');
110
111         $userId = getOrCreateUser(
112             $id['mode'], trim($id['name']), trim($id['imageurl']),
113             trim($id['email'])
114         );
115         $me = Urls::full(Urls::user($userId));
116
117         $code = base64_encode(
118             http_build_query(
119                 [
120                     'emoji'     => '\360\237\222\251',
121                     'me'        => $me,
122                     'scope'     => $scope,
123                     'signature' => 'FIXME',
124                 ]
125             )
126         );
127
128         //redirect back to client
129         $url = new \Net_URL2($redirect_uri);
130         $url->setQueryVariable('code', $code);
131         $url->setQueryVariable('me', $me);
132         $url->setQueryVariable('state', $state);
133         header('Location: ' . $url->getURL());
134         exit();
135     } else {
136         //auth code verification
137         $code         = base64_decode(verifyParameter($_POST, 'code'));
138         $redirect_uri = verifyUrlParameter($_POST, 'redirect_uri');
139         $client_id    = verifyUrlParameter($_POST, 'client_id');
140         $state        = getOptionalParameter($_POST, 'state', null);
141
142         parse_str($code, $codeParts);
143         $emoji     = verifyParameter($codeParts, 'emoji');
144         $signature = verifyParameter($codeParts, 'signature');
145         $me        = verifyUrlParameter($codeParts, 'me');
146         if ($emoji != '\360\237\222\251') {
147             error('Dog poo missing');
148         }
149         if ($signature != 'FIXME') {
150             error('Invalid signature');
151         }
152         header('HTTP/1.0 200 OK');
153         header('Content-type: application/x-www-form-urlencoded');
154         echo http_build_query(['me' => $me]);
155         exit();
156     }
157 } else if ($_SERVER['REQUEST_METHOD'] == 'HEAD') {
158     //indieauth.com makes a HEAD request at first
159     header('HTTP/1.0 200 OK');
160     exit();
161 } else {
162     error('Unsupported HTTP request method');
163 }
164 ?>