MediaWiki REL1_31
OATHAuthKey.php
Go to the documentation of this file.
1<?php
31 const MAIN_TOKEN = 1;
32
37 const SCRATCH_TOKEN = -1;
38
40 private $secret;
41
44
50 public static function newFromRandom() {
51 $object = new self(
53 []
54 );
55
56 $object->regenerateScratchTokens();
57
58 return $object;
59 }
60
65 public function __construct( $secret, array $scratchTokens ) {
66 // Currently harcoded values; might be used in future
67 $this->secret = [
68 'mode' => 'hotp',
69 'secret' => $secret,
70 'period' => 30,
71 'algorithm' => 'SHA1',
72 ];
73 $this->scratchTokens = $scratchTokens;
74 }
75
79 public function getSecret() {
80 return $this->secret['secret'];
81 }
82
86 public function getScratchTokens() {
88 }
89
99 public function verifyToken( $token, OATHUser $user ) {
100 global $wgOATHAuthWindowRadius;
101
102 if ( $this->secret['mode'] !== 'hotp' ) {
103 throw new \DomainException( 'OATHAuth extension does not support non-HOTP tokens' );
104 }
105
106 // Prevent replay attacks
107 $memc = ObjectCache::newAnything( [] );
108 $uid = CentralIdLookup::factory()->centralIdFromLocalUser( $user->getUser() );
109 $memcKey = wfMemcKey( 'oathauth', 'usedtokens', $uid );
110 $lastWindow = (int)$memc->get( $memcKey );
111
112 $retval = false;
114 Base32::decode( $this->secret['secret'] ),
115 $this->secret['period'], -$wgOATHAuthWindowRadius, $wgOATHAuthWindowRadius
116 );
117
118 // Remove any whitespace from the received token, which can be an intended group seperator
119 // or trimmeable whitespace
120 $token = preg_replace( '/\s+/', '', $token );
121
122 // Check to see if the user's given token is in the list of tokens generated
123 // for the time window.
124 foreach ( $results as $window => $result ) {
125 if ( $window > $lastWindow && $result->toHOTP( 6 ) === $token ) {
126 $lastWindow = $window;
128 break;
129 }
130 }
131
132 // See if the user is using a scratch token
133 if ( !$retval ) {
134 $length = count( $this->scratchTokens );
135 // Detect condition where all scratch tokens have been used
136 if ( $length == 1 && "" === $this->scratchTokens[0] ) {
137 $retval = false;
138 } else {
139 for ( $i = 0; $i < $length; $i++ ) {
140 if ( $token === $this->scratchTokens[$i] ) {
141 // If there is a scratch token, remove it from the scratch token list
142 unset( $this->scratchTokens[$i] );
144 $user->setKey( $this );
145 $oathrepo->persist( $user );
146 // Only return true if we removed it from the database
148 break;
149 }
150 }
151 }
152 }
153
154 if ( $retval ) {
155 $memc->set(
156 $memcKey,
157 $lastWindow,
158 $this->secret['period'] * ( 1 + 2 * $wgOATHAuthWindowRadius )
159 );
160 } else {
161 // Increase rate limit counter for failed request
162 $user->getUser()->pingLimiter( 'badoath' );
163 }
164
165 return $retval;
166 }
167
168 public function regenerateScratchTokens() {
169 $scratchTokens = [];
170 for ( $i = 0; $i < 5; $i++ ) {
171 array_push( $scratchTokens, Base32::encode( MWCryptRand::generate( 10, true ) ) );
172 }
173 $this->scratchTokens = $scratchTokens;
174 }
175
183 public function isScratchToken( $token ) {
184 $token = preg_replace( '/\s+/', '', $token );
185 return in_array( $token, $this->scratchTokens, true );
186 }
187}
wfMemcKey()
Make a cache key for the local wiki.
static decode($b32)
Decodes a base32 string into a binary string according to RFC 4648.
Definition base32.php:48
static encode($string)
Encodes a binary string into a base32 string according to RFC 4648 (no padding).
Definition base32.php:80
static generateByTimeWindow( $key, $window, $min=-1, $max=1, $timestamp=false)
Generate a HOTP key collection based on a timestamp and window size all keys that could exist between...
Definition hotp.php:72
static generate( $bytes, $forceStrong=false)
Generate a run of (ideally) cryptographically random data and return it in raw binary form.
static getOATHUserRepository()
Get the singleton OATH user repository.
This program is free software; you can redistribute it and/or modify it under the terms of the GNU Ge...
static newFromRandom()
Make a new key from random values.
regenerateScratchTokens()
isScratchToken( $token)
Check if a token is one of the scratch tokens for this two factor key.
const SCRATCH_TOKEN
Represents that a token corresponds to a scratch token.
__construct( $secret, array $scratchTokens)
array $secret
Two factor binary secret.
const MAIN_TOKEN
Represents that a token corresponds to the main secret.
string[] $scratchTokens
List of scratch tokens.
verifyToken( $token, OATHUser $user)
Verify a token against the secret or scratch tokens.
This program is free software; you can redistribute it and/or modify it under the terms of the GNU Ge...
Definition OATHUser.php:24
please add to it if you re going to add events to the MediaWiki code where normally authentication against an external auth plugin would be creating a local account incomplete not yet checked for validity & $retval
Definition hooks.txt:266