मैं एक कोणीय और स्प्रिंग एप्लिकेशन के लिए TOTP सॉफ्ट टोकन के साथ मल्टी-फैक्टर प्रमाणीकरण जोड़ना चाहता हूं, जबकि स्प्रिंग बूट सिक्योरिटी स्टार्टर के डिफॉल्ट्स के लिए जितना संभव हो सके सब कुछ पास रखता हूं ।
टोकन-सत्यापन स्थानीय रूप से होता है (एरोगियर-ओटीपी-जावा लाइब्रेरी के साथ), कोई तीसरा पक्ष एपीआई प्रदाता नहीं।
उपयोगकर्ता कार्यों के लिए टोकन सेट करना, लेकिन स्प्रिंग सिक्योरिटी ऑथेंटिकेशन मैनेजर / प्रोवाइडर्स का लाभ उठाकर उन्हें मान्य नहीं करता है।
टी एल; डॉ
- स्प्रिंग बूट सिक्योरिटी स्टार्टर कॉन्फ़िगर सिस्टम में एक अतिरिक्त AuthenticationProvider को एकीकृत करने का आधिकारिक तरीका क्या है ?
- रिप्ले हमलों को रोकने के लिए अनुशंसित तरीके क्या हैं?
दीर्घ संस्करण
एपीआई में एक एंडपॉइंट /auth/token
होता है, जिसमें से सामने वाले को उपयोगकर्ता नाम और पासवर्ड प्रदान करके JWT टोकन मिल सकता है। प्रतिक्रिया भी एक प्रमाणीकरण-स्थिति, जो या तो किया जा सकता है शामिल प्रमाणीकृत या PRE_AUTHENTICATED_MFA_REQUIRED ।
यदि उपयोगकर्ता को एमएफए की आवश्यकता होती है, तो टोकन जारी किया गया एकल प्राधिकारी PRE_AUTHENTICATED_MFA_REQUIRED
और 5 मिनट की समाप्ति समय के साथ जारी किया जाता है । यह उपयोगकर्ता को समापन बिंदु तक पहुंचने की अनुमति देता है /auth/mfa-token
जहां वे अपने प्रमाणक ऐप से टीओटीपी कोड प्रदान कर सकते हैं और साइट तक पहुंचने के लिए पूरी तरह से प्रमाणित टोकन प्राप्त कर सकते हैं।
प्रदाता और टोकन
मैंने अपना रिवाज बनाया है MfaAuthenticationProvider
जो लागू होता है AuthenticationProvider
:
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
// validate the OTP code
}
@Override
public boolean supports(Class<?> authentication) {
return OneTimePasswordAuthenticationToken.class.isAssignableFrom(authentication);
}
और OneTimePasswordAuthenticationToken
जो AbstractAuthenticationToken
उपयोगकर्ता नाम (हस्ताक्षरित JWT से लिया गया) और OTP कोड को रखने के लिए विस्तारित होता है।
कॉन्फ़िग
मेरे पास मेरा रिवाज है WebSecurityConfigurerAdapter
, जहां मैं अपने रिवाज AuthenticationProvider
को जोड़ता हूं http.authenticationProvider()
। JavaDoc में आने से यह सही जगह लगता है:
का उपयोग करने के लिए एक अतिरिक्त प्रमाणीकरण जोड़ने की अनुमति देता है
मेरे संबंधित भाग SecurityConfig
इस तरह दिखते हैं।
@Configuration
@EnableWebSecurity
@EnableJpaAuditing(auditorAwareRef = "appSecurityAuditorAware")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final TokenProvider tokenProvider;
public SecurityConfig(TokenProvider tokenProvider) {
this.tokenProvider = tokenProvider;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authenticationProvider(new MfaAuthenticationProvider());
http.authorizeRequests()
// Public endpoints, HTML, Assets, Error Pages and Login
.antMatchers("/", "favicon.ico", "/asset/**", "/pages/**", "/api/auth/token").permitAll()
// MFA auth endpoint
.antMatchers("/api/auth/mfa-token").hasAuthority(ROLE_PRE_AUTH_MFA_REQUIRED)
// much more config
नियंत्रक
AuthController
है AuthenticationManagerBuilder
इंजेक्शन और यह सब एक साथ खींच रहा है।
@RestController
@RequestMapping(AUTH)
public class AuthController {
private final TokenProvider tokenProvider;
private final AuthenticationManagerBuilder authenticationManagerBuilder;
public AuthController(TokenProvider tokenProvider, AuthenticationManagerBuilder authenticationManagerBuilder) {
this.tokenProvider = tokenProvider;
this.authenticationManagerBuilder = authenticationManagerBuilder;
}
@PostMapping("/mfa-token")
public ResponseEntity<Token> mfaToken(@Valid @RequestBody OneTimePassword oneTimePassword) {
var username = SecurityUtils.getCurrentUserLogin().orElse("");
var authenticationToken = new OneTimePasswordAuthenticationToken(username, oneTimePassword.getCode());
var authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken);
// rest of class
हालाँकि, /auth/mfa-token
इस त्रुटि के खिलाफ पोस्टिंग :
"error": "Forbidden",
"message": "Access Denied",
"trace": "org.springframework.security.authentication.ProviderNotFoundException: No AuthenticationProvider found for de.....OneTimePasswordAuthenticationToken
स्प्रिंग सुरक्षा मेरे प्रमाणीकरण प्रदाता को क्यों नहीं उठाती है? नियंत्रक को डीबग करना मुझे दिखाता है कि DaoAuthenticationProvider
एकमात्र प्रमाणीकरण प्रदाता है AuthenticationProviderManager
।
अगर मैं अपने MfaAuthenticationProvider
सेम के रूप में उजागर करता हूं , तो यह एकमात्र प्रदाता है जो पंजीकृत है, इसलिए मुझे इसके विपरीत मिलता है:
No AuthenticationProvider found for org.springframework.security.authentication.UsernamePasswordAuthenticationToken.
तो, मैं दोनों कैसे प्राप्त करूं?
मेरा प्रश्न
स्प्रिंग बूट सिक्योरिटी स्टार्टर कॉन्फ़िगर सिस्टम AuthenticationProvider
में एक अतिरिक्त को एकीकृत करने के लिए अनुशंसित तरीका क्या है , ताकि मुझे दोनों मिलें, और मेरा अपना रिवाज ? मैं स्प्रिंग बूट स्क्यूरिटी स्टार्टर के डिफॉल्ट्स रखना चाहता हूं और इसके अलावा मेरे खुद के प्रदाता भी हैं।DaoAuthenticationProvider
MfaAuthenticationProvider
रिप्ले हमले की रोकथाम
मुझे पता है कि ओटीपी एल्गोरिथ्म समय के स्लाइस जिसमें कोड मान्य है के भीतर रिप्ले हमलों से खुद की रक्षा नहीं करता है; RFC 6238 यह स्पष्ट करता है
पहले OTP के लिए सफल सत्यापन जारी होने के बाद सत्यापनकर्ता को OTP के दूसरे प्रयास को स्वीकार नहीं करना चाहिए, जो एक OTP के केवल एक बार उपयोग को सुनिश्चित करता है।
मैं सोच रहा था कि क्या सुरक्षा को लागू करने का कोई अनुशंसित तरीका है। चूंकि ओटीपी टोकन समय आधारित है इसलिए मैं उपयोगकर्ता के मॉडल पर अंतिम सफल लॉगिन को संग्रहीत करने के बारे में सोच रहा हूं और सुनिश्चित करता हूं कि प्रति 30 सेकंड के समय के स्लाइस में केवल एक सफल लॉगिन है। यह निश्चित रूप से उपयोगकर्ता मॉडल पर सिंक्रनाइज़ेशन का मतलब है। कोई बेहतर तरीका?
धन्यवाद।
-
पुनश्च: चूंकि यह सुरक्षा के बारे में एक प्रश्न है, जिसे मैं विश्वसनीय और / या आधिकारिक स्रोतों से उत्तर आरेखण के लिए देख रहा हूं। धन्यवाद।