ECE366 - Lesson 13
Authentication on the Cloud
Instructor: Professor Hong
Early Final Presentations
## More Hosting on the Cloud
## webservice/Webconfig.java
```java
package ece366.rpsjdbc.webservice;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // Apply CORS to all endpoints
.allowedOrigins("http://moosetracks.eastus.azurecontainer.io") // Allow requests from your frontend
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") // Allow specific HTTP methods
.allowedHeaders("*") // Allow all headers, including Authorization
.allowCredentials(true); // Allow cookies or Authorization headers
}
}
```
## webservice/WebserviceController.java
```
package ece366.rpsjdbc.webservice;
import ece366.rpsjdbc.DatabaseConnectionManager;
import ece366.rpsjdbc.Player;
import ece366.rpsjdbc.PlayerDAO;
import org.springframework.web.bind.annotation.*;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/api")
public class WebserviceController {
private final PlayerDAO playerDAO;
private final boolean isTestMode;
// Constructor for dependency injection (used in tests)
public WebserviceController(PlayerDAO playerDAO) {
this.playerDAO = playerDAO;
this.isTestMode = true; // Indicates that this is a test instance
}
// Default constructor (used in production)
public WebserviceController() {
this.isTestMode = false;
this.playerDAO = null; // Will be initialized dynamically in production
}
@GetMapping("/testPlayer")
public String getTestPlayer() {
return "TEST PLAYER";
}
@GetMapping("/player/{id}")
public Player getPlayerById(@PathVariable Long id) {
System.out.println("getPlayerById: " + id);
try {
// Use injected PlayerDAO in test mode, otherwise create it dynamically
PlayerDAO dao = isTestMode ? playerDAO : createPlayerDAO();
Player player = dao.findById(id);
System.out.println(player.toString());
return player;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
// Factory method to create PlayerDAO in production
private PlayerDAO createPlayerDAO() throws SQLException {
DatabaseConnectionManager dcm = new DatabaseConnectionManager("localhost", "rps", "postgres", "password");
Connection connection = dcm.getConnection();
return new PlayerDAO(connection);
}
}
```
## Azure Review
```
az login
az acr login --name ece366acr
az acr login --name ece366acr --expose-token
docker compose build
docker compose push
az container create --resource-group ece366rg --file deploy-aci.yaml
```
## Add Back Security Dependencies in pom.xml
```
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
```
## resources/application.properties
```
spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://www.googleapis.com/service_accounts/v1/jwk/securetoken%40system.gserviceaccount.com
```
## config/SecurityConfig.java
```
package ece366.rpsjdbc.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable()) // Disable CSRF using the new syntax
.authorizeHttpRequests(authorize -> authorize
.requestMatchers(org.springframework.http.HttpMethod.OPTIONS, "/**").permitAll() // Allow all OPTIONS requests
.requestMatchers("/api/**").permitAll() // Allow all requests to /api/** without authentication
.anyRequest().authenticated() // Require authentication for other endpoints
);
return http.build();
}
}
```
##
```
package ece366.rpsjdbc.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(csrf -> csrf.disable()) // Disable CSRF for simplicity
.authorizeHttpRequests(authorize -> authorize
.requestMatchers(org.springframework.http.HttpMethod.OPTIONS, "/**").permitAll() // Allow all OPTIONS requests
.requestMatchers("/api/testPlayer").permitAll() // Allow unauthenticated access to test endpoint
.anyRequest().authenticated() // Require authentication for all other endpoints
)
.oauth2ResourceServer(oauth2 -> oauth2
.jwt(jwt -> jwt.jwtAuthenticationConverter(jwtAuthenticationConverter())) // Use JwtConfigurer
);
return http.build();
}
private JwtAuthenticationConverter jwtAuthenticationConverter() {
JwtAuthenticationConverter converter = new JwtAuthenticationConverter();
// Customize the converter if needed (e.g., map roles or claims)
return converter;
}
}
```