All integrations

Java Integration

Spring Boot and enterprise applications

Turalogin provides a strong fit for enterprise and internal tools built with Java. Start auth to send a magic link email, handle the callback when users click the link, and verify the token. Tokens work cleanly with Spring Security if desired.

  • Works with Spring Boot, Spring MVC, and other frameworks
  • Magic link flow with customizable callback URL
  • Standard REST client integration (RestTemplate, WebClient)
  • Compatible with Spring Security
  • Enterprise-grade session management

Implementation Examples

1. Application Configuration

Configure your environment variables in application.properties or application.yml.

application.properties
1# Your Turalogin API key from the dashboard
2turalogin.api-key=${TURALOGIN_API_KEY}
3
4# The URL where magic links will redirect to
5# Development:
6turalogin.validation-url=http://localhost:8080/auth/callback
7
8# Production (update for your domain):
9# turalogin.validation-url=https://myapp.com/auth/callback

2. Start Authentication

Create a REST controller endpoint to initiate authentication. This sends a magic link to the user's email.

AuthController.java
1@RestController
2@RequestMapping("/auth")
3public class AuthController {
4
5 private final TuraloginService turaloginService;
6
7 public AuthController(TuraloginService turaloginService) {
8 this.turaloginService = turaloginService;
9 }
10
11 @PostMapping("/start")
12 public ResponseEntity<Map<String, Object>> startAuth(
13 @RequestBody StartAuthRequest request) {
14 try {
15 turaloginService.startAuth(request.getEmail());
16 return ResponseEntity.ok(Map.of(
17 "success", true,
18 "message", "Check your email for the login link"
19 ));
20 } catch (TuraloginException e) {
21 return ResponseEntity
22 .status(e.getStatus())
23 .body(Map.of("error", e.getMessage()));
24 }
25 }
26}
27
28// Request DTO
29public record StartAuthRequest(String email) {}

3. Handle Magic Link Callback

Create a callback endpoint that receives the token from the magic link and verifies it.

AuthController.java
1@GetMapping("/callback")
2public ResponseEntity<?> authCallback(
3 @RequestParam String token,
4 HttpSession session,
5 HttpServletResponse response) {
6 try {
7 AuthResult result = turaloginService.verifyToken(token);
8
9 // Store user in session
10 session.setAttribute("userId", result.user().id());
11 session.setAttribute("email", result.user().email());
12 session.setAttribute("turaloginToken", result.token());
13
14 // Redirect to dashboard
15 response.sendRedirect("/dashboard");
16 return null;
17
18 } catch (TuraloginException e) {
19 try {
20 response.sendRedirect("/login?error=verification_failed");
21 } catch (IOException ex) {
22 // Handle redirect error
23 }
24 return null;
25 } catch (IOException e) {
26 return ResponseEntity.status(500).body(Map.of("error", "Redirect failed"));
27 }
28}
29
30@PostMapping("/logout")
31public ResponseEntity<?> logout(HttpSession session) {
32 session.invalidate();
33 return ResponseEntity.ok(Map.of("success", true));
34}

4. Turalogin Service

A service class that encapsulates all Turalogin API interactions.

TuraloginService.java
1@Service
2public class TuraloginService {
3
4 private final RestTemplate restTemplate;
5 private final String apiKey;
6 private final String validationUrl;
7 private final String baseUrl = "https://api.turalogin.com/api/v1";
8
9 public TuraloginService(
10 RestTemplateBuilder restTemplateBuilder,
11 @Value("${turalogin.api-key}") String apiKey,
12 @Value("${turalogin.validation-url}") String validationUrl) {
13 this.restTemplate = restTemplateBuilder.build();
14 this.apiKey = apiKey;
15 this.validationUrl = validationUrl;
16 }
17
18 public void startAuth(String email) {
19 HttpHeaders headers = createHeaders();
20
21 Map<String, String> body = Map.of(
22 "email", email,
23 "validationUrl", validationUrl // Where the magic link redirects to
24 );
25 HttpEntity<Map<String, String>> request = new HttpEntity<>(body, headers);
26
27 try {
28 restTemplate.postForEntity(
29 baseUrl + "/auth/start",
30 request,
31 Map.class
32 );
33 } catch (HttpClientErrorException e) {
34 throw handleError(e);
35 }
36 }
37
38 public AuthResult verifyToken(String token) {
39 HttpHeaders headers = createHeaders();
40
41 Map<String, String> body = Map.of("sessionId", token);
42 HttpEntity<Map<String, String>> request = new HttpEntity<>(body, headers);
43
44 try {
45 ResponseEntity<AuthResponse> response = restTemplate.postForEntity(
46 baseUrl + "/auth/verify",
47 request,
48 AuthResponse.class
49 );
50 AuthResponse authResponse = response.getBody();
51 return new AuthResult(
52 authResponse.token(),
53 new User(
54 authResponse.user().get("id"),
55 authResponse.user().get("email")
56 )
57 );
58 } catch (HttpClientErrorException e) {
59 throw handleError(e);
60 }
61 }
62
63 private HttpHeaders createHeaders() {
64 HttpHeaders headers = new HttpHeaders();
65 headers.setBearerAuth(apiKey);
66 headers.setContentType(MediaType.APPLICATION_JSON);
67 return headers;
68 }
69
70 private TuraloginException handleError(HttpClientErrorException e) {
71 return new TuraloginException(
72 e.getResponseBodyAsString(),
73 e.getStatusCode().value()
74 );
75 }
76}

5. Authentication Filter

A filter to protect routes and validate sessions.

AuthenticationFilter.java
1@Component
2public class AuthenticationFilter extends OncePerRequestFilter {
3
4 private final List<String> publicPaths = List.of(
5 "/auth/start",
6 "/auth/callback",
7 "/public"
8 );
9
10 @Override
11 protected void doFilterInternal(
12 HttpServletRequest request,
13 HttpServletResponse response,
14 FilterChain filterChain) throws ServletException, IOException {
15
16 String path = request.getRequestURI();
17
18 // Skip public paths
19 if (publicPaths.stream().anyMatch(path::startsWith)) {
20 filterChain.doFilter(request, response);
21 return;
22 }
23
24 // Check for valid session
25 HttpSession session = request.getSession(false);
26 if (session == null || session.getAttribute("userId") == null) {
27 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
28 response.setContentType(MediaType.APPLICATION_JSON_VALUE);
29 response.getWriter().write(
30 "{\"error\": \"Authentication required\"}"
31 );
32 return;
33 }
34
35 filterChain.doFilter(request, response);
36 }
37}

6. Exception Handling

Global exception handler for Turalogin-related errors.

GlobalExceptionHandler.java
1@RestControllerAdvice
2public class GlobalExceptionHandler {
3
4 @ExceptionHandler(TuraloginException.class)
5 public ResponseEntity<Map<String, String>> handleTuraloginException(
6 TuraloginException e) {
7
8 String message = switch (e.getCode()) {
9 case "INVALID_EMAIL" -> "Please provide a valid email address";
10 case "SESSION_EXPIRED" -> "Login link has expired. Please try again.";
11 case "INVALID_TOKEN" -> "Invalid login link";
12 case "RATE_LIMITED" -> "Too many attempts. Please wait a moment.";
13 default -> "Authentication error. Please try again.";
14 };
15
16 return ResponseEntity
17 .status(e.getStatus())
18 .body(Map.of("error", message, "code", e.getCode()));
19 }
20}
21
22// Exception class
23public class TuraloginException extends RuntimeException {
24 private final String code;
25 private final int status;
26
27 public TuraloginException(String message, String code, int status) {
28 super(message);
29 this.code = code;
30 this.status = status;
31 }
32
33 public String getCode() { return code; }
34 public int getStatus() { return status; }
35}

Complete Spring Boot Application

A complete Spring Boot application configuration with magic link authentication.

Application.java
1@SpringBootApplication
2public class Application {
3 public static void main(String[] args) {
4 SpringApplication.run(Application.class, args);
5 }
6}
7
8// application.yml
9/*
10turalogin:
11 api-key: ${TURALOGIN_API_KEY}
12 validation-url: ${APP_LOGIN_VALIDATION_URL:http://localhost:8080/auth/callback}
13
14server:
15 servlet:
16 session:
17 timeout: 7d
18 cookie:
19 http-only: true
20 secure: true
21 same-site: lax
22*/
23
24// Protected Controller Example
25@RestController
26@RequestMapping("/api")
27public class ApiController {
28
29 @GetMapping("/me")
30 public ResponseEntity<?> getCurrentUser(HttpSession session) {
31 String userId = (String) session.getAttribute("userId");
32 String email = (String) session.getAttribute("email");
33
34 return ResponseEntity.ok(Map.of(
35 "id", userId,
36 "email", email
37 ));
38 }
39
40 @GetMapping("/dashboard")
41 public ResponseEntity<?> getDashboard(HttpSession session) {
42 String email = (String) session.getAttribute("email");
43
44 return ResponseEntity.ok(Map.of(
45 "message", "Welcome to the dashboard, " + email + "!"
46 ));
47 }
48}
49
50// Security Configuration (if using Spring Security)
51@Configuration
52@EnableWebSecurity
53public class SecurityConfig {
54
55 @Bean
56 public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
57 http
58 .csrf(csrf -> csrf.disable())
59 .sessionManagement(session ->
60 session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED))
61 .authorizeHttpRequests(auth -> auth
62 .requestMatchers("/auth/**").permitAll()
63 .requestMatchers("/public/**").permitAll()
64 .anyRequest().authenticated()
65 );
66
67 return http.build();
68 }
69}

Ready to integrate?

Create your Turalogin account and get your API key in minutes.