Skip to content

Commit d773919

Browse files
committed
Move checks to functions
1 parent c5a3049 commit d773919

File tree

1 file changed

+44
-22
lines changed

1 file changed

+44
-22
lines changed

src/Surfnet/AzureMfa/Application/Service/AzureMfaService.php

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
use Symfony\Component\HttpFoundation\RequestStack;
4040
use Symfony\Component\HttpFoundation\Session\SessionInterface;
4141
use Exception;
42+
use Surfnet\AzureMfa\Domain\Institution\ValueObject\Institution;
43+
use Surfnet\AzureMfa\Domain\Institution\ValueObject\IdentityProviderInterface;
4244

4345
/**
4446
* @SuppressWarnings("PHPMD.CouplingBetweenObjects")
@@ -182,36 +184,61 @@ public function handleResponse(Request $request): User
182184
$user = $this->session->get('user');
183185
assert($user instanceof User);
184186

185-
// Retrieve its institution and identity provider
186-
$this->logger->info('Match the user email address '.$user->getEmailAddress().'to one of the registered institutions');
187+
$this->logger->info('Match the user email address '.$user->getEmailAddress().' to one of the registered institutions');
187188
$institution = $this->matchingService->findInstitutionByEmail($user->getEmailAddress());
188189
if (is_null($institution)) {
189190
throw new AzureADException('The Institution could not be found using the users mail address');
190191
}
192+
191193
$azureMfaIdentityProvider = $this->identityProviderCache->build($institution->getName());
194+
$assertion = $this->processResponseWithOptionalMetadataRefresh(
195+
$request,
196+
$azureMfaIdentityProvider,
197+
$institution
198+
);
199+
200+
$this->validateResponseAttributes($assertion->getAttributes(), $user, $institution, $azureMfaIdentityProvider);
201+
202+
$this->logger->info(sprintf(
203+
'The mail attribute in the response %s matched the email address of the registering/authenticating user: %s',
204+
$assertion->getAttributes()[self::SAML_EMAIL_ATTRIBUTE],
205+
$user->getEmailAddress()->getEmailAddress()
206+
));
192207

208+
return $user;
209+
}
210+
211+
private function processResponseWithOptionalMetadataRefresh(
212+
Request $request,
213+
IdentityProviderInterface $azureMfaIdentityProvider,
214+
Institution $institution
215+
): mixed {
193216
try {
194217
$this->logger->info('Process the SAML Response');
195-
$assertion = $this->postBinding->processResponse(
218+
219+
return $this->postBinding->processResponse(
196220
$request,
197221
$azureMfaIdentityProvider,
198222
$this->serviceProvider
199223
);
200224
} catch (Exception $e) {
201-
// If the signature validation fails, we try to rebuild the identity provider
202-
// This will effectively refresh the metadata for the institution
203-
// Todo: refactor this to be more robust, e.g. by checking the exception type
204225
if (!$institution->supportsMetadataUpdate() || $e->getMessage() !== 'Unable to validate Signature') {
205226
throw $e;
206227
}
207228

208-
$this->logger->info(sprintf('Unable to validate signature refreshing metadata for %s', $institution->getName()->getInstitutionName()));
229+
$this->logger->info(sprintf(
230+
'Unable to validate signature refreshing metadata for %s',
231+
$institution->getName()->getInstitutionName()
232+
));
209233

210234
$azureMfaIdentityProvider = $this->identityProviderCache->rebuild($institution->getName());
211235

212-
$this->logger->info('Reprocess the SAML Response from '.$institution->getName()->getInstitutionName().' after updating the metadata');
236+
$this->logger->info(
237+
'Reprocess the SAML Response from '.$institution->getName()->getInstitutionName().' after updating the metadata'
238+
);
239+
213240
try {
214-
$assertion = $this->postBinding->processResponse(
241+
return $this->postBinding->processResponse(
215242
$request,
216243
$azureMfaIdentityProvider,
217244
$this->serviceProvider
@@ -224,12 +251,14 @@ public function handleResponse(Request $request): User
224251
throw $retryException;
225252
}
226253
}
254+
}
227255

228-
$attributes = $assertion->getAttributes();
229-
230-
// If the IDP was an AzureAD endpoint (the entityID or Issuer starts with https://login.microsoftonline.com/, or preferably an config parameter in institutions.yaml)
231-
// the SAML response attribute 'http://schemas.microsoft.com/claims/authnmethodsreferences'
232-
// should contain 'http://schemas.microsoft.com/claims/multipleauthn'
256+
private function validateResponseAttributes(
257+
array $attributes,
258+
User $user,
259+
Institution $institution,
260+
IdentityProviderInterface $azureMfaIdentityProvider
261+
): void {
233262
if ($azureMfaIdentityProvider->isAzureAD()) {
234263
$this->logger->info($institution->getName()->getInstitutionName().' is an AzureAD IdP. Validating authnmethodsreferences in the response.');
235264
if (!isset($attributes['http://schemas.microsoft.com/claims/authnmethodsreferences']) || !in_array('http://schemas.microsoft.com/claims/multipleauthn', $attributes['http://schemas.microsoft.com/claims/authnmethodsreferences'])) {
@@ -241,7 +270,7 @@ public function handleResponse(Request $request): User
241270

242271
if (!isset($attributes[self::SAML_EMAIL_ATTRIBUTE])) {
243272
throw new MissingMailAttributeException(
244-
'The mail attribute in the Azure MFA assertion from '.$institution->getName()->getInstitutionName(). 'was missing'
273+
'The mail attribute in the Azure MFA assertion from '.$institution->getName()->getInstitutionName().' was missing'
245274
);
246275
}
247276

@@ -253,12 +282,5 @@ public function handleResponse(Request $request): User
253282
strtolower($user->getEmailAddress()->getEmailAddress())
254283
));
255284
}
256-
257-
$this->logger->info(sprintf(
258-
'The mail attribute in the response %s matched the email address of the registering/authenticating user: %s',
259-
$attributes[self::SAML_EMAIL_ATTRIBUTE],
260-
$user->getEmailAddress()->getEmailAddress()
261-
));
262-
return $user;
263285
}
264286
}

0 commit comments

Comments
 (0)