MediaWiki master
BotPasswordSessionProvider.php
Go to the documentation of this file.
1<?php
25
26use InvalidArgumentException;
33
40 private $grantsInfo;
41
43 private $isApiRequest;
44
53 public function __construct( GrantsInfo $grantsInfo, array $params = [] ) {
54 if ( !isset( $params['sessionCookieName'] ) ) {
55 $params['sessionCookieName'] = '_BPsession';
56 }
57 parent::__construct( $params );
58
59 if ( !isset( $params['priority'] ) ) {
60 throw new InvalidArgumentException( __METHOD__ . ': priority must be specified' );
61 }
62 if ( $params['priority'] < SessionInfo::MIN_PRIORITY ||
64 ) {
65 throw new InvalidArgumentException( __METHOD__ . ': Invalid priority' );
66 }
67
68 $this->priority = $params['priority'];
69
70 $this->grantsInfo = $grantsInfo;
71
72 $this->isApiRequest = $params['isApiRequest']
73 ?? ( defined( 'MW_API' ) || defined( 'MW_REST_API' ) );
74 }
75
76 public function provideSessionInfo( WebRequest $request ) {
77 // Only relevant for the (Action or REST) API
78 if ( !$this->isApiRequest ) {
79 return null;
80 }
81
82 // Enabled?
83 if ( !$this->getConfig()->get( MainConfigNames::EnableBotPasswords ) ) {
84 return null;
85 }
86
87 // Have a session ID?
88 $id = $this->getSessionIdFromCookie( $request );
89 if ( $id === null ) {
90 return null;
91 }
92
93 return new SessionInfo( $this->priority, [
94 'provider' => $this,
95 'id' => $id,
96 'persisted' => true
97 ] );
98 }
99
100 public function newSessionInfo( $id = null ) {
101 // We don't activate by default
102 return null;
103 }
104
112 public function newSessionForRequest( User $user, BotPassword $bp, WebRequest $request ) {
113 $id = $this->getSessionIdFromCookie( $request );
115 'provider' => $this,
116 'id' => $id,
117 'userInfo' => UserInfo::newFromUser( $user, true ),
118 'persisted' => $id !== null,
119 'metadata' => [
120 'centralId' => $bp->getUserCentralId(),
121 'appId' => $bp->getAppId(),
122 'token' => $bp->getToken(),
123 'rights' => $this->grantsInfo->getGrantRights( $bp->getGrants() ),
124 'restrictions' => $bp->getRestrictions()->toJson(),
125 ],
126 ] );
127 $session = $this->getManager()->getSessionFromInfo( $info, $request );
128 $session->persist();
129 return $session;
130 }
131
136 public function refreshSessionInfo( SessionInfo $info, WebRequest $request, &$metadata ) {
137 $missingKeys = array_diff(
138 [ 'centralId', 'appId', 'token' ],
139 array_keys( $metadata )
140 );
141 if ( $missingKeys ) {
142 $this->logger->info( 'Session "{session}": Missing metadata: {missing}', [
143 'session' => $info->__toString(),
144 'missing' => implode( ', ', $missingKeys ),
145 ] );
146 return false;
147 }
148
149 $bp = BotPassword::newFromCentralId( $metadata['centralId'], $metadata['appId'] );
150 if ( !$bp ) {
151 $this->logger->info(
152 'Session "{session}": No BotPassword for {centralId} {appId}',
153 [
154 'session' => $info->__toString(),
155 'centralId' => $metadata['centralId'],
156 'appId' => $metadata['appId'],
157 ] );
158 return false;
159 }
160
161 if ( !hash_equals( $metadata['token'], $bp->getToken() ) ) {
162 $this->logger->info( 'Session "{session}": BotPassword token check failed', [
163 'session' => $info->__toString(),
164 'centralId' => $metadata['centralId'],
165 'appId' => $metadata['appId'],
166 ] );
167 return false;
168 }
169
170 $status = $bp->getRestrictions()->check( $request );
171 if ( !$status->isOK() ) {
172 $this->logger->info(
173 'Session "{session}": Restrictions check failed',
174 [
175 'session' => $info->__toString(),
176 'restrictions' => $status->getValue(),
177 'centralId' => $metadata['centralId'],
178 'appId' => $metadata['appId'],
179 ] );
180 return false;
181 }
182
183 // Update saved rights
184 $metadata['rights'] = $this->grantsInfo->getGrantRights( $bp->getGrants() );
185
186 return true;
187 }
188
193 public function preventSessionsForUser( $username ) {
194 BotPassword::removeAllPasswordsForUser( $username );
195 }
196
197 public function getAllowedUserRights( SessionBackend $backend ) {
198 if ( $backend->getProvider() !== $this ) {
199 throw new InvalidArgumentException( 'Backend\'s provider isn\'t $this' );
200 }
201 $data = $backend->getProviderMetadata();
202 if ( $data && isset( $data['rights'] ) && is_array( $data['rights'] ) ) {
203 return $data['rights'];
204 }
205
206 // Should never happen
207 $this->logger->debug( __METHOD__ . ': No provider metadata, returning no rights allowed' );
208 return [];
209 }
210
211 public function getRestrictions( ?array $data ): ?MWRestrictions {
212 if ( $data && isset( $data['restrictions'] ) && is_string( $data['restrictions'] ) ) {
213 try {
214 return MWRestrictions::newFromJson( $data['restrictions'] );
215 } catch ( InvalidArgumentException $e ) {
216 $this->logger->warning( __METHOD__ . ': Failed to parse restrictions: {restrictions}', [
217 'restrictions' => $data['restrictions']
218 ] );
219 return null;
220 }
221 }
222 return null;
223 }
224}
array $params
The job parameters.
if(!defined('MW_SETUP_CALLBACK'))
Definition WebStart.php:81
A class to check request restrictions expressed as a JSON object.
A class containing constants representing the names of configuration variables.
const EnableBotPasswords
Name constant for the EnableBotPasswords setting, for use with Config::get()
Users can authorize applications to use their account via OAuth.
The WebRequest class encapsulates getting at data passed in the URL or via a POSTed form,...
newSessionForRequest(User $user, BotPassword $bp, WebRequest $request)
Create a new session for a request.
provideSessionInfo(WebRequest $request)
Provide session info for a request.
__construct(GrantsInfo $grantsInfo, array $params=[])
preventSessionsForUser( $username)
Prevent future sessions for the user.If the provider is capable of returning a SessionInfo with a ver...
getRestrictions(?array $data)
Fetch any restrictions imposed on logins or actions when this session is active.
getAllowedUserRights(SessionBackend $backend)
Fetch the rights allowed the user when the specified session is active.
newSessionInfo( $id=null)
Provide session info for a new, empty session.
refreshSessionInfo(SessionInfo $info, WebRequest $request, &$metadata)
Validate a loaded SessionInfo and refresh provider metadata.This is similar in purpose to the 'Sessio...
An ImmutableSessionProviderWithCookie doesn't persist the user, but optionally can use a cookie to su...
getSessionIdFromCookie(WebRequest $request)
Get the session ID from the cookie, if any.
This is the actual workhorse for Session.
getProviderMetadata()
Fetch provider metadata.
getProvider()
Fetch the SessionProvider for this session.
Value object returned by SessionProvider.
const MIN_PRIORITY
Minimum allowed priority.
const MAX_PRIORITY
Maximum allowed priority.
getManager()
Get the session manager.
static newFromUser(User $user, $verified=false)
Create an instance from an existing User object.
Definition UserInfo.php:125
Utility class for bot passwords.
getUserCentralId()
Get the central user ID.
internal since 1.36
Definition User.php:93