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