/
LoginHandler.php
171 lines (148 loc) · 5.32 KB
/
LoginHandler.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
<?php
namespace SilverStripe\RealMe\Authenticator;
use Exception;
use Psr\Log\LoggerInterface;
use SilverStripe\Control\Controller;
use SilverStripe\Control\HTTPRequest;
use SilverStripe\Control\RequestHandler;
use SilverStripe\Core\Convert;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\RealMe\Exception as RealMeException;
use SilverStripe\RealMe\Extension\MemberExtension;
use SilverStripe\RealMe\RealMeService;
use SilverStripe\Security\Member;
use SilverStripe\Security\AuthenticationHandler;
use SilverStripe\Security\Security;
class LoginHandler extends RequestHandler
{
private static $dependencies = [
'service' => '%$' . RealMeService::class,
];
/**
* @var array
*/
private static $url_handlers = [
'' => 'login',
];
/**
* @var array
* @config
*/
private static $allowed_actions = [
'login',
'acs',
];
/**
* @var string Called link on this handler
*/
private $link;
/**
* @var RealMeService
*/
protected $service;
/**
* @param string $link The URL to recreate this request handler
*/
public function __construct($link)
{
$this->link = $link;
parent::__construct();
}
/**
* Return a link to this request handler.
* The link returned is supplied in the constructor
* @param null|string $action
* @return string
*/
public function link($action = null)
{
if ($action) {
return Controller::join_links($this->link, $action);
}
return $this->link;
}
/**
* URL handler for the log-in screen
*
* @return array
*/
public function login(HTTPRequest $request)
{
if ($backURL = $this->service->getBackURL($request)) {
$request->getSession()->set('RealMeBackURL', $backURL);
}
return [
'Form' => $this->loginForm(),
];
}
public function loginForm()
{
return LoginForm::create($this, 'acs');
}
public function acs(HTTPRequest $request)
{
try {
$authenticated = $this->service->enforceLogin($request);
$session = $request->getSession();
if ($authenticated === true) {
$authData = $this->service->getAuthData();
// If more session vars are set here, they must be cleared in realmeLogout()
$session->set('RealMe.SessionData', serialize($authData));
$session->set('RealMe.OriginalResponse', $request->postVar('SAMLResponse'));
$realMeServiceConfig = RealMeService::config();
if ($realMeServiceConfig->get('sync_with_local_member_database') === true) {
if ($realMeServiceConfig->get('integration_type') === RealMeService::TYPE_ASSERT) {
throw new RealMeException(
'NameID is transient for ASSERT - it cannot be used to identify a user between sessions.',
RealMeException::PERSISTING_TRANSIENT_ID
);
}
if (!Member::has_extension(MemberExtension::class)) {
throw new RealMeException(
'The RealMe MemberExtension should be used when syncing with a local database',
RealMeException::MISSING_MEMBER_EXTENSION
);
}
if (!$authData->getMember()->isInDb()) {
$authData->getMember()->write();
}
if ($realMeServiceConfig->get('login_member_after_authentication') === true) {
Injector::inst()->get(AuthenticationHandler::class)->login($authData->getMember());
}
}
// Redirect to the default BackURL
return $this->redirect($this->getBackURL() ?: $this->service->getBackURL($request));
} else {
if (is_string($this->service->getLastError())) {
$session->set('RealMe.LastErrorMessage', $this->service->getLastError());
// Redirect to the 'Error Back URL' if set
$backUrl = $this->service->getErrorBackURL($request);
if ($backUrl) {
return $this->redirect($backUrl);
} else {
// Fallback to homepage
return $this->redirect('/');
}
}
throw new RealMeException(
'Attempted access of ACS action without SAML response',
RealMeException::MISSING_AUTHN_RESPONSE
);
}
} catch (Exception $e) {
$msg = sprintf(
'Error during RealMe authentication process. Code: %d, Message: %s',
$e->getCode(),
$e->getMessage()
);
Injector::inst()->get(LoggerInterface::class)->info($msg);
}
return Security::permissionFailure(
$this,
_t(
RealMeService::class . '.LOGINFAILURE',
'Unfortunately we\'re not able to log you in through RealMe right now. Please try again shortly.'
)
);
}
}