22e3de9f0195375b6425083b2575ac94a958b97c
[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     $userId = Urls::userId($me);
64     if ($userId !== null) {
65         $storage = new Storage();
66         $rowUser = $storage->getUser($userId);
67         if ($rowUser !== null) {
68             $id['mode']     = 'data';
69             $id['name']     = $rowUser->user_name;
70             $id['imageurl'] = $rowUser->user_imageurl;
71             if ($id['imageurl'] == Urls::userImg()) {
72                 $id['imageurl'] = '';
73             }
74         }
75     }
76
77     //let the user choose his identity
78     header('HTTP/1.0 200 OK');
79     render(
80         'auth-choose',
81         array(
82             'auth' => array(
83                 'redirect_uri'  => $redirect_uri,
84                 'client_id'     => $client_id,
85                 'state'         => $state,
86                 'response_type' => $response_type,
87                 'scope'         => $scope,
88             ),
89             'id' => $id,
90             'formaction' => '/auth.php?action=login',
91         )
92     );
93     exit();
94 } else if ($_SERVER['REQUEST_METHOD'] == 'POST') {
95     if (isset($_GET['action']) && $_GET['action'] == 'login') {
96         //log the user in
97         $auth = $_POST['auth'];
98         $redirect_uri  = verifyUrlParameter($auth, 'redirect_uri');
99         $client_id     = verifyUrlParameter($auth, 'client_id');
100         $state         = getOptionalParameter($auth, 'state', null);
101         $response_type = getOptionalParameter($auth, 'response_type', 'id');
102         $scope         = getOptionalParameter($auth, 'scope', null);
103
104         $id = $_POST['id'];
105         verifyParameter($id, 'mode');
106
107         $userId = getOrCreateUser(
108             $id['mode'], trim($id['name']), trim($id['imageurl']),
109             trim($id['email'])
110         );
111         $me = Urls::full(Urls::user($userId));
112
113         $code = base64_encode(
114             http_build_query(
115                 [
116                     'emoji'     => '\360\237\222\251',
117                     'me'        => $me,
118                     'scope'     => $scope,
119                     'signature' => 'FIXME',
120                 ]
121             )
122         );
123
124         //redirect back to client
125         $url = new \Net_URL2($redirect_uri);
126         $url->setQueryVariable('code', $code);
127         $url->setQueryVariable('me', $me);
128         $url->setQueryVariable('state', $state);
129         header('Location: ' . $url->getURL());
130         exit();
131     } else {
132         //auth code verification
133         $code         = base64_decode(verifyParameter($_POST, 'code'));
134         $redirect_uri = verifyUrlParameter($_POST, 'redirect_uri');
135         $client_id    = verifyUrlParameter($_POST, 'client_id');
136         $state        = getOptionalParameter($_POST, 'state', null);
137
138         parse_str($code, $codeParts);
139         $emoji     = verifyParameter($codeParts, 'emoji');
140         $signature = verifyParameter($codeParts, 'signature');
141         $me        = verifyUrlParameter($codeParts, 'me');
142         if ($emoji != '\360\237\222\251') {
143             error('Dog poo missing');
144         }
145         if ($signature != 'FIXME') {
146             error('Invalid signature');
147         }
148         header('HTTP/1.0 200 OK');
149         header('Content-type: application/x-www-form-urlencoded');
150         echo http_build_query(['me' => $me]);
151         exit();
152     }
153 } else if ($_SERVER['REQUEST_METHOD'] == 'HEAD') {
154     //indieauth.com makes a HEAD request at first
155     header('HTTP/1.0 200 OK');
156     exit();
157 } else {
158     error('Unsupported HTTP request method');
159 }
160 ?>