Conditions | 17 |
Total Lines | 100 |
Lines | 0 |
Ratio | 0 % |
Changes | 0 |
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like org.apereo.cas.authentication.DefaultAuthenticationContextValidator.validate(Authentication,String,RegisteredService) often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
1 | package org.apereo.cas.authentication; |
||
61 | @Override |
||
62 | public Pair<Boolean, Optional<MultifactorAuthenticationProvider>> validate(final Authentication authentication, |
||
63 | final String requestedContext, |
||
64 | final RegisteredService service) { |
||
65 | final Map<String, Object> attrs = authentication.getAttributes(); |
||
66 | final Object ctxAttr = attrs.get(this.authenticationContextAttribute); |
||
67 | final Collection<Object> contexts = CollectionUtils.toCollection(ctxAttr); |
||
68 | LOGGER.debug("Attempting to match requested authentication context [{}] against [{}]", requestedContext, contexts); |
||
69 | |||
70 | final Map<String, MultifactorAuthenticationProvider> providerMap = |
||
71 | MultifactorAuthenticationUtils.getAvailableMultifactorAuthenticationProviders(this.applicationContext); |
||
72 | if (providerMap == null) { |
||
73 | LOGGER.debug("No multifactor authentication providers are configured"); |
||
74 | return Pair.of(Boolean.FALSE, Optional.empty()); |
||
75 | } |
||
76 | final Optional<MultifactorAuthenticationProvider> requestedProvider = locateRequestedProvider(providerMap.values(), requestedContext); |
||
77 | |||
78 | if (!requestedProvider.isPresent()) { |
||
79 | LOGGER.debug("Requested authentication provider cannot be recognized."); |
||
80 | return Pair.of(Boolean.FALSE, Optional.empty()); |
||
81 | } |
||
82 | |||
83 | if (contexts.stream().filter(ctx -> ctx.toString().equals(requestedContext)).count() > 0) { |
||
84 | LOGGER.debug("Requested authentication context [{}] is satisfied", requestedContext); |
||
85 | return Pair.of(Boolean.TRUE, requestedProvider); |
||
86 | } |
||
87 | |||
88 | |||
89 | if (StringUtils.isNotBlank(this.mfaTrustedAuthnAttributeName) |
||
90 | && attrs.containsKey(this.mfaTrustedAuthnAttributeName)) { |
||
91 | LOGGER.debug("Requested authentication context [{}] is satisfied since device is already trusted", requestedContext); |
||
92 | return Pair.of(Boolean.TRUE, requestedProvider); |
||
93 | } |
||
94 | |||
95 | if (attrs.containsKey(MultifactorAuthenticationProviderBypass.AUTHENTICATION_ATTRIBUTE_BYPASS_MFA) |
||
96 | && attrs.containsKey(MultifactorAuthenticationProviderBypass.AUTHENTICATION_ATTRIBUTE_BYPASS_MFA_PROVIDER)) { |
||
97 | |||
98 | final boolean isBypass = Boolean.class.cast(attrs.get(MultifactorAuthenticationProviderBypass.AUTHENTICATION_ATTRIBUTE_BYPASS_MFA)); |
||
99 | final String bypassedId = attrs.get(MultifactorAuthenticationProviderBypass.AUTHENTICATION_ATTRIBUTE_BYPASS_MFA_PROVIDER).toString(); |
||
100 | |||
101 | LOGGER.debug("Found multifactor authentication bypass attributes for provider [{}]", bypassedId); |
||
102 | |||
103 | if (isBypass && StringUtils.equals(bypassedId, requestedContext)) { |
||
104 | LOGGER.debug("Requested authentication context [{}] is satisfied given mfa was bypassed for the authentication attempt", |
||
105 | requestedContext); |
||
106 | return Pair.of(Boolean.TRUE, requestedProvider); |
||
107 | } |
||
108 | |||
109 | LOGGER.debug("Either multifactor authentication was not bypassed or the requested context [{}] does not match the bypassed provider [{}]", |
||
110 | requestedProvider, bypassedId); |
||
111 | } |
||
112 | |||
113 | final Collection<MultifactorAuthenticationProvider> satisfiedProviders = |
||
114 | getSatisfiedAuthenticationProviders(authentication, providerMap.values()); |
||
115 | |||
116 | if (satisfiedProviders == null) { |
||
117 | LOGGER.warn("No satisfied multifactor authentication providers are recorded in the current authentication context."); |
||
118 | return Pair.of(Boolean.FALSE, requestedProvider); |
||
119 | } |
||
120 | |||
121 | if (!satisfiedProviders.isEmpty()) { |
||
122 | final MultifactorAuthenticationProvider[] providers = satisfiedProviders.toArray(new MultifactorAuthenticationProvider[]{}); |
||
123 | OrderComparator.sortIfNecessary(providers); |
||
124 | final Optional<MultifactorAuthenticationProvider> result = Arrays.stream(providers) |
||
125 | .filter(provider -> { |
||
126 | final MultifactorAuthenticationProvider p = requestedProvider.get(); |
||
127 | return provider.equals(p) || provider.getOrder() >= p.getOrder(); |
||
128 | }) |
||
129 | .findFirst(); |
||
130 | |||
131 | if (result.isPresent()) { |
||
132 | LOGGER.debug("Current provider [{}] already satisfies the authentication requirements of [{}]; proceed with flow normally.", |
||
133 | result.get(), requestedProvider); |
||
134 | return Pair.of(Boolean.TRUE, requestedProvider); |
||
135 | } |
||
136 | } |
||
137 | |||
138 | LOGGER.debug("No multifactor providers could be located to satisfy the requested context for [{}]", requestedProvider); |
||
139 | |||
140 | final RegisteredServiceMultifactorPolicy.FailureModes mode = getMultifactorFailureModeForService(service); |
||
141 | if (mode == RegisteredServiceMultifactorPolicy.FailureModes.PHANTOM) { |
||
142 | if (!requestedProvider.get().isAvailable(service)) { |
||
143 | LOGGER.debug("Service [{}] is configured to use a [{}] failure mode for multifactor authentication policy. " |
||
144 | + "Since provider [{}] is unavailable at the moment, CAS will knowingly allow [{}] as a satisfied criteria " |
||
145 | + "of the present authentication context", service.getServiceId(), |
||
146 | mode, requestedProvider, requestedContext); |
||
147 | return Pair.of(Boolean.TRUE, requestedProvider); |
||
148 | } |
||
149 | } |
||
150 | if (mode == RegisteredServiceMultifactorPolicy.FailureModes.OPEN) { |
||
151 | if (!requestedProvider.get().isAvailable(service)) { |
||
152 | LOGGER.debug("Service [{}] is configured to use a [{}] failure mode for multifactor authentication policy and " |
||
153 | + "since provider [{}] is unavailable at the moment, CAS will consider the authentication satisfied " |
||
154 | + "without the presence of [{}]", service.getServiceId(), |
||
155 | mode, requestedProvider, requestedContext); |
||
156 | return Pair.of(Boolean.TRUE, satisfiedProviders.stream().findFirst()); |
||
157 | } |
||
158 | } |
||
159 | |||
160 | return Pair.of(Boolean.FALSE, requestedProvider); |
||
161 | } |
||
199 |