I'm looking to make a grant_type = password login from a service with Feign to the Spring OAuth2 server. I've confirmed the OAuth2 server works when I make a normal REST call. But when trying with Feign, it fails.
In my service I have:
#Component
#Scope("prototype")
#FeignClient(url = "http://localhost:9999/uaa")
public interface AuthClient {
#RequestMapping(value="/oauth/token", method=RequestMethod.POST)
#Headers({"Authorization: Basic some_base64encoded_client_secret_here=="})
public LoginResponse login(
#Param("username") String username, #Param("password") String password, #Param("grant_type") String grantType);
}
I get this error:
java.lang.ClassCastException: Cannot cast com.sun.proxy.$Proxy129 to org.springframework.web.bind.annotation.RequestMapping
Most examples I find show how to intercept Feign to use OAuth headers/etc. and assume the access token already exists. But this is not my issue. I don't have an access token yet because I'm trying to get the access token from logging in. Any ideas on how I can log in using Feign?
You can map your own response like this:
#Component
#FeignClient(name = "authClient", url = "http://localhost:8080")
public interface AuthClient {
#RequestMapping(value="/oauth/token", method= RequestMethod.POST)
AuthResponse login(#RequestParam("grant_type") String grantType, #RequestParam("username") String username,
#RequestParam("password") String password, #RequestParam("scope") String scope);
#JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
class AuthResponse {
String access_token;
String token_type;
String refresh_token;
String expires_in;
}
}
public class AuthService {
private final AuthClient authClient;
public AuthService(AuthClient authClient) {
this.authClient = authClient;
}
public AuthClient.AuthResponse authenticate(String login, String password, String scopes) {
return this.authClient.login("password", "admin", "admin", "read+write");
}
}
You can register a request interceptor to add Authorization headers at every request:
#Bean
public BasicAuthRequestInterceptor basicAuthRequestInterceptor() {
return new BasicAuthRequestInterceptor("clientId", "clientSecret");
}
This code works with a sample Spring Security OAuth2 server.
Related
I am working on a Spring Boot application that take the username and password of an existing user on the system and then generates a JWT token. I copied it from a tutorial and I changed it in order to work with my specific use cases. The logic is pretty clear to me but I have a big doubt about how the user is authenticated on the system. Following I will try to explain you as this is structured and what is my doubt.
The JWT generation token system is composed by two different micro services, that are:
The GET-USER-WS: this microservice simmply use Hibernate\JPA to retrieve the information of a specific user in the system. Basically it contains a controller class calling a service class that itself calla JPA repository in order to retrieve a specific user information:
#RestController
#RequestMapping("api/users")
#Log
public class UserController {
#Autowired
UserService userService;
#GetMapping(value = "/{email}", produces = "application/json")
public ResponseEntity<User> getUserByEmail(#PathVariable("email") String eMail) throws NotFoundException {
log.info(String.format("****** Get the user with eMail %s *******", eMail) );
User user = userService.getUserByEmail(eMail);
if (user == null)
{
String ErrMsg = String.format("The user with eMail %s was not found", eMail);
log.warning(ErrMsg);
throw new NotFoundException(ErrMsg);
}
return new ResponseEntity<User>(user, HttpStatus.OK);
}
}
As you can see this controller contains an API that use the e-mail parameter (that is the username on the system) and return a JSON containing the information of this user.
Then I have a second microservice (named AUTH-SERVER-JWT) that is the one that call the previous API in order to obtain the user information that will be used to generate the JWT token. To keep the description as simple as possible it contains this controller class:
#RestController
//#CrossOrigin(origins = "http://localhost:4200")
public class JwtAuthenticationRestController {
#Value("${sicurezza.header}")
private String tokenHeader;
#Autowired
private AuthenticationManager authenticationManager;
#Autowired
private JwtTokenUtil jwtTokenUtil;
#Autowired
#Qualifier("customUserDetailsService")
//private UserDetailsService userDetailsService;
private CustomUserDetailsService userDetailsService;
private static final Logger logger = LoggerFactory.getLogger(JwtAuthenticationRestController.class);
#PostMapping(value = "${sicurezza.uri}")
public ResponseEntity<?> createAuthenticationToken(#RequestBody JwtTokenRequest authenticationRequest)
throws AuthenticationException {
logger.info("Autenticazione e Generazione Token");
authenticate(authenticationRequest.getUsername(), authenticationRequest.getPassword());
//final UserDetails userDetails = userDetailsService.loadUserByUsername(authenticationRequest.getUsername());
final UserDetailsWrapper userDetailsWrapper = userDetailsService.loadCompleteUserByUsername(authenticationRequest.getUsername());
final String token = jwtTokenUtil.generateToken(userDetailsWrapper);
logger.warn(String.format("Token %s", token));
return ResponseEntity.ok(new JwtTokenResponse(token));
}
#RequestMapping(value = "${sicurezza.uri}", method = RequestMethod.GET)
public ResponseEntity<?> refreshAndGetAuthenticationToken(HttpServletRequest request)
throws Exception
{
String authToken = request.getHeader(tokenHeader);
if (authToken == null || authToken.length() < 7)
{
throw new Exception("Token assente o non valido!");
}
final String token = authToken.substring(7);
if (jwtTokenUtil.canTokenBeRefreshed(token))
{
String refreshedToken = jwtTokenUtil.refreshToken(token);
return ResponseEntity.ok(new JwtTokenResponse(refreshedToken));
}
else
{
return ResponseEntity.badRequest().body(null);
}
}
#ExceptionHandler({ AuthenticationException.class })
public ResponseEntity<String> handleAuthenticationException(AuthenticationException e)
{
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(e.getMessage());
}
private void authenticate(String username, String password)
{
Objects.requireNonNull(username);
Objects.requireNonNull(password);
try {
/// ???
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
}
catch (DisabledException e)
{
logger.warn("UTENTE DISABILITATO");
throw new AuthenticationException("UTENTE DISABILITATO", e);
}
catch (BadCredentialsException e)
{
logger.warn("CREDENZIALI NON VALIDE");
throw new AuthenticationException("CREDENZIALI NON VALIDE", e);
}
}
}
This class contains two method, the first one is used to generate a brand new JWT token and the second one it is used to refresh an existing JWT token. Consider now the first use case (generate a brand new JWT token) related to the createAuthenticationToken() method. This method take as input parmether the information related to the JWT token request: #RequestBody JwtTokenRequest authenticationRequest. Bascailly the JwtTokenRequest is a simple DTO object like this:
#Data
public class JwtTokenRequest implements Serializable
{
private static final long serialVersionUID = -3558537416135446309L;
private String username;
private String password;
}
So the payload in the body request will be something like this:
{
"username": "xxx#gmail.com",
"password": "password"
}
NOTE: in my DB I have a user having this username and password so the user will be retrieved and authenticated on the system.
As you can see the first effective operation that the createAuthenticationToken() method do is:
authenticate(authenticationRequest.getUsername(), authenticationRequest.getPassword());
Basically it is calling the authenticate() method defined in the same class passing to it the previous credential ("username": "xxx#gmail.com" and "password": "password").
As you can see this is my authenticate() method
private void authenticate(String username, String password)
{
Objects.requireNonNull(username);
Objects.requireNonNull(password);
try {
/// ???
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
}
catch (DisabledException e)
{
logger.warn("UTENTE DISABILITATO");
throw new AuthenticationException("UTENTE DISABILITATO", e);
}
catch (BadCredentialsException e)
{
logger.warn("CREDENTIAL ERROR");
throw new AuthenticationException(""CREDENTIAL ERROR", e);
}
}
Basically it is passing these credential to the authenticate() method defined into the injected Spring Security AuthenticationManager instance, by this line:
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password));
This method seems to be able to authenticate or not these credentials. And it seems to works fine because if I put a wrong username or password it goes into the CREDENTIAL ERROR case and it throw the AuthenticationException exception.
And here my huge doubt: why it works?!?! How is it possible? If you come back to the createAuthenticationToken() controller method you can see that it does these two operation in the following order:
authenticate(authenticationRequest.getUsername(), authenticationRequest.getPassword());
final UserDetailsWrapper userDetailsWrapper = userDetailsService.loadCompleteUserByUsername(authenticationRequest.getUsername());
It first perform the authenticate() method (that should check if theusername and password that was sent are correct), then call the service method that retrieve the user information.
Sho how the authenticate() method is able to check if the credential sent in the original payload are correct?
Usually, the implementation of AuthenticationManager is a ProviderManager, which will loop through all the configured AuthenticationProviders and try to authenticate using the credentials provided.
One of the AuthenticationProviders, is DaoAuthenticationProvider, which supports a UsernamePasswordAuthenticationToken and uses the UserDetailsService (you have a customUserDetailsService) to retrieve the user and compare the password using the configured PasswordEncoder.
There is a more detailed explanation in the reference docs about the Authentication Architecture.
Problem
I'm trying to create an app that uses Auth0 SPA + React on the frontend to auth users without ever having to deal with passwords. Then, I'd like to secure any endpoints I create using an Auth server that I'm required to create using the Spring Framework.
Just to clarify, the flow would be
Frontend ->
Auth through Auth0 ->
Redirect to users dashboard on frontend ->
Make HTTP request to endpoint sending JWT returned from Auth0 ->
Endpoint makes request to my Auth Server sending JWT returned from Auth0 ->
Auth server either either returns 401 or user object based on JWT ->
Endpoint grabs data specific to that user from DB ->
Returns data to frontend
I've managed to get my frontend to work just fine using the Quickstart Guide that Auth0 provides but I'm having a lot of trouble figuring out how to get my Auth Service to verify the user.
I believe I've come to the conclusion that I need to create an "API" on Auth0 and grab an access token and use that to validate the JWT, which in this case is just the access token and not the JWT that my frontend contains. I've also got this part working but there doesn't seem to be a way to know who the user is. When testing this "API", after sending a valid request I am returned
{
"iss": "https://${username}.auth0.com/",
"sub": "${alphanumericCharacters}#clients",
"aud": "${ApiIdentifier}",
"iat": ${issuedAt},
"exp": ${expiresAt},
"azp": "${alphanumericCharacters}",
"gty": "client-credentials"
}
While it's good to know I'm on the right track I can't seem to figure out what to do with this response to find the user.
Expected
I expect to be able to identify a specific user after validating an access_token from my Auth Service
Code
I don't have much code to show but I'll provide what I can from my Auth Service
SecurityConfiguration.java
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Value("${auth0.audience}")
private String audience;
#Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri}")
private String issuer;
#Override
public void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeRequests()
.mvcMatchers("/api/validate")
.authenticated()
.and()
.oauth2ResourceServer()
.jwt();
}
#Bean
JwtDecoder jwtDecoder() {
NimbusJwtDecoderJwkSupport jwtDecoder = (NimbusJwtDecoderJwkSupport)
JwtDecoders.fromOidcIssuerLocation(issuer);
OAuth2TokenValidator<Jwt> audienceValidator = new AudienceValidator(audience);
OAuth2TokenValidator<Jwt> withIssuer = JwtValidators.createDefaultWithIssuer(issuer);
OAuth2TokenValidator<Jwt> withAudience = new DelegatingOAuth2TokenValidator<>(withIssuer, audienceValidator);
jwtDecoder.setJwtValidator(withAudience);
return jwtDecoder;
}
}
AudienceValidator.java
public class AudienceValidator implements OAuth2TokenValidator<Jwt> {
private final String audience;
public AudienceValidator(String audience) {
this.audience = audience;
}
public OAuth2TokenValidatorResult validate(Jwt jwt) {
OAuth2Error error = new OAuth2Error("invalid_token", "The required audience is missing", null);
if (jwt.getAudience().contains(audience)) {
return OAuth2TokenValidatorResult.success();
}
return OAuth2TokenValidatorResult.failure(error);
}
}
ValidateController.java
#RestController
#RequestMapping("/api/validate")
public class ValidateController {
#GetMapping
public boolean validate() {
return true; // only returns if successfully authed
}
}
After reading through the docs I've found my solution.
It turns out that I don't need to create an "API" on Auth0 but instead need to use my Applications endspoint(s) from Auth0. Auth0 provides many endpoints based on your account that you can take advantage of from any of your applications (CLI, Server, Client, etc.) as long as you can:
Make an HTTP Request
Provide credentials
So the way to get a users information is explained here.
Data flow
Using my projects auth/data flow it's pretty much:
Using #auth0/auth0-spa-js on the frontend, you can grab a users access token after a successful auth by using the getTokenSilently() method.
Send up HTTP request to your Rest Service
Rest Service sends that token to your Auth Service
Auth Service sends GET request to https://myAuth0Username.auth0.com/userinfo with the Authorization: Bearer ${access_token} header. Example
If successfully authed from Auth0
Returns your users information such as "name", "email", etc.
Else
Returns a 403 Forbidden HTTP Status
Auth Service then returns user object to Rest Service
Rest Service then does necessary logic for that endpoint (DB query, another HTTP request, etc.)
Example Auth Service endpoint to validate tokens and return a user
ValidateController.java
package x.SpringTodo_Auth.Controllers;
import x.SpringTodo_Auth.Models.User;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
#RestController
#RequestMapping("/api/validate")
public class ValidateController {
#GetMapping
public Object validate() {
// Create and set the "Authorization" header before sending HTTP request
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer " + access_token);
HttpEntity<String> entity = new HttpEntity<>("headers", headers);
// Use the "RestTemplate" API provided by Spring to make the HTTP request
RestTemplate restTemplate = new RestTemplate();
Object user = restTemplate.exchange("https://myAuth0Username.auth0.com/userinfo", HttpMethod.POST, entity, User.class);
return user;
}
}
User.java (This is the class passed to the restTemplate.exchange(...) method as the last argument
package x.SpringTodo_Auth.Models;
public class User {
private String sub;
private String given_name;
private String family_name;
private String nickname;
private String name;
private String picture;
private String locale;
private String updated_at;
private String email;
private boolean email_verified;
// Getters/setters (or you can use Lombok)
}
I'm building a 3rd party app to authenticate with Contact Center Express. The documentation is necessary, but insufficient to accomplish this. For example,
https://developer.cisco.com/docs/contact-center-express/#!cisco-identity-service-client-sdk-guide/during-agent-login
// Get Access Token for the received Authorization Code
String redirectURI = config.getRedirectUri();
AccessToken token = client.getAccessToken(authCode, redirectURI);
When and where do you redirect the user to Contact Center to authenticate? I observed that Finesse will redirect the user to
https://contactcenter.example.com:8553/ids/v1/oauth/authorize?redirect_uri=https%3A%2F%2Ffinesse.example.com%3A443%2Fdesktop%2Fsso%2Fauthcode&client_id=8a75xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&state=aHR0cHM6Ly92bS1mLWZpbi1hLmRldi5pbi5zcGluc2NpLmNvbS9kZXNrdG9wL2pfaWRlbnRpdHlfY2hlY2s%2FZXJyb3I9dHJ1ZQlhcHBsb2dpbg%3D%3D&response_type=code
But where is it specified to use the identity service (IDS) path /ids/v1/oauth/authorize? And is state a required parameter? And does the IDS SDK handle the callback path /desktop/sso/authcode? I imagine that it doesn't but what are the parameters that will be sent to it? I'm using Spring framework.
Am I to reverse engineer the whole process, or is there additional documentation that I am missing?
Even after I receive an OAuth token, how would I use it to make other REST calls to other Cisco products? The Finesse REST APIs only mention HTTP basic authentication. There is no mention of headers for "Authorization: Bearer" tokens.
https://developer.cisco.com/docs/finesse/#!sign-in-to-finesse/sign-in-to-finesse
I had to reverse engineer it following all the redirects.
#Controller
public class SSOController {
#Autowired
private IdSClientConfigurationImpl config;
#Autowired
private IdSClient client;
#PostMapping("/login")
public String login(#RequestParam(name="user", required=true) String user) {
// redirect the user to the Cisco Contact Center Express Identity Service
String redirectURI = config.getRedirectUri();
String clientId = config.getClientId();
URI uri = UriComponentsBuilder
.fromUriString("https://contact-center-express:8553/ids/v1/oauth/authorize")
.queryParam("redirect_uri", "{redirect_uri}")
.queryParam("client_id", "{client_id}")
// .queryParam("state", "{state}") // base64 encoded
.queryParam("response_type", "code")
.build(redirectURI, clientId);
return "redirect:"+uri.toString();
}
#GetMapping("/idscallback")
public String idscallback(
#RequestParam(name="code", required=true) String code,
#RequestParam(name="state", required=false) String state,
HttpSession session) throws IdSClientException {
// Get Access Token for the received Authorization Code
String redirectURI = config.getRedirectUri();
AccessToken token = client.getAccessToken(code, redirectURI); // why do I need redirectURI when it's already redirected?
String accessTokenString = token.getAccess_token();
session.setAttribute("token", accessTokenString);
// model.addAttribute("token", accessTokenString);
return "redirect:/";
}
And in a bean far, far away...
#Bean
public IdSClientConfigurationImpl config() throws IOException, IdSClientException {
ClassPathResource idsclientResource = new ClassPathResource("idsclient.properties");
IdSClientConfigurationImpl config = new IdSClientConfigurationImpl(idsclientResource.getFile().getPath());
// IdSClientConfigurationImpl config = new IdSClientConfigurationImpl("src/main/resources/idsclient.properties");
config.load();
return config;
}
#Bean
public IdSClient setupIdsClient() throws IOException, IdSClientException {
IdSClient client = IdSClientFactory.getIdSClient();
client.setTLSContext(createSSLTrustManager(), createHostnameVerifier());
// client.setTLSContext(arg0, arg1) // use secure trust manager and hostname verifier in production
client.init(config);
return client;
}
private X509TrustManager createSSLTrustManager() {
X509TrustManager tm = new TrustAllX509TrustManager();
return tm;
}
private HostnameVerifier createHostnameVerifier() {
HostnameVerifier hv = new SkipAllHostNameVerifier();
return hv;
}
I am newbie to Java(came from .Net background), I am trying to write a RESTful service using Jersey framework. I referred this link http://www.vogella.com/tutorials/REST/article.html
#GET
#Produces(MediaType.TEXT_PLAIN)
public String sayPlainTextHello() {
return "Hello Jersey";
}
Now I want to get the HTTPContext in the above method. Basically I am looking to get the logged-in user name, I hope that should be available using HttpContext.Request.
I am using windows NT authentication.
Can anybody please tell me how to get the HTTPContext/User information inside the Java RESTful service.
You can use below code to get the HTTPContext in your REST resource.
public class RestResource {
#Context
private HttpServletRequest httpServletRequest;
#GET
#Produces(MediaType.TEXT_PLAIN)
public String sayPlainTextHello() {
RequestContext requestContext = (RequestContext) httpServletRequest.getAttribute(RequestConstants.REQUEST_CONTEXT);
// Get whatever the value set in your request context
String userName = requestContext.requestContext.getQueryString("userName");
return userName;
}
}
let me know if you need any help.
Short answer
The SecurityContext injected with the #Context annotation allows you to access security related information. It has a request scope and hold details about the user who is authenticated.
For other types that can be injected with #Context, check this answer.
Long answer
You must mind that REST authentication must be stateless. That is, you must not rely on sessions stored on server side, hence the user credentials must be sent in each request. In other words, each request must be authenticated/authorized. To understand this concept, this answer may be insightful.
See below how the SecurityContext can be used in a couple of approaches to secure your application:
Basic authentication
The Basic authentication scheme described in the RFC 7617 with HTTPS is a common and efficent approach to secure a REST application:
2. The 'Basic' Authentication Scheme
The Basic authentication scheme is based on the model that the client
needs to authenticate itself with a user-id and a password for each
protection space ("realm"). [...] The server will service the request only if it can validate
the user-id and password for the protection space applying to the
requested resource.
[...]
To receive authorization, the client
obtains the user-id and password from the user,
constructs the user-pass by concatenating the user-id, a single
colon (:) character, and the password,
encodes the user-pass into an octet sequence,
and obtains the basic-credentials by encoding this octet sequence
using Base64 into a sequence of US-ASCII
characters.
[...]
If the user agent wishes to send the user-id "Aladdin" and password
"open sesame", it would use the following header field:
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
[...]
You could use a ContainerRequestFilter to extract the user credentials from the Authorization request header, authenticate them against your authentication provider and then set a SecurityContext with the username for the request. The AuthenticationService implementation is up to you:
#Provider
#Priority(Priorities.AUTHENTICATION)
class AuthenticationFilter implements ContainerRequestFilter {
#Inject
private AuthenticationService authenticationService;
#Override
public void filter(ContainerRequestFilter requestContext) {
// Get the HTTP Authorization header from the request
String authorizationHeader =
requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
// Check if the HTTP Authorization header is present and formatted correctly
if (authorizationHeader == null || !authorizationHeader.startsWith("Basic ")) {
throw new NotAuthorizedException("Authorization header must be provided");
}
// Extract the Basic authentication token from the HTTP Authorization header
String token = authorizationHeader.substring("Basic".length()).trim();
// Decodes the token
String credentials = Base64.getDecoder().decode(token);
String[] split = decoded.split(":");
try {
// Authenticate the credentials against in your authentication provider
authenticationService.authenticate(split[0], split[1]);
} catch (Exception e) {
requestContext.abortWith(
Response.status(Response.Status.UNAUTHORIZED).build());
}
// Updates the security context for the request
SecurityContext securityContext = requestContext.getSecurityContext();
requestContext.setSecurityContext(
new CustomSecurityContext(split[0], securityContext.isSecure()));
}
}
A custom SecurityContext implementation could be like:
public class CustomSecurityContext implements SecurityContext {
private final String username;
private final boolean secure;
public BasicSecurityContext(String username, boolean secure) {
this.username = username;
this.secure = secure;
}
#Override
public Principal getUserPrincipal() {
return new Principal() {
#Override
public String getName() {
return username;
}
};
}
#Override
public String getAuthenticationScheme() {
return SecurityContext.BASIC_AUTH;
}
#Override
public boolean isSecure() {
return secure;
}
#Override
public boolean isUserInRole(String role) {
return true;
}
}
Then the SecurityContext can be injected in any resource class using the #Context annotation:
#Path("/example")
public class MyResource {
#Context
private SecurityContext securityContext;
...
}
It also can be injected in a resource method parameter:
#GET
#Path("/{id}")
#Produces(MediaType.APPLICATION_JSON)
public Response myResourceMethod(#PathParam("id") Long id,
#Context SecurityContext securityContext) {
...
}
And then get the Principal from the SecurityContext:
Principal principal = securityContext.getUserPrincipal();
String username = principal.getName();
Token based authentication
In an authentication scheme based on tokens, the token becomes a credential of the user.
Hard credentials such as username and password are exchanged for a token that must be sent in each request then the server can perform authentication/authorization. Tokens can be valid for a short amount of time, can be revoked, can carry scope details (what can be requested with the token), etc.
For more details, have a look at this answer. The SecurityContext can be used in the same way as explained above.
I'm trying to secure my rest services written using dropwizard by Apache Shiro. First I initialized the security manager in the main method.
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
Then I wrote a service for user login.
if (!currentUser.isAuthenticated()) {
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
token.setRememberMe(true);
try {
currentUser.login(token);
System.out.println("USER AUTHENTICATED!!!!!!!!");
} catch (Exception uae) {
System.out.println("Error logging in .................");
}
}
Then I declared a method with some java annotations.
#RequiresAuthentication
#RequiresRoles("admin")
#GET
#Path("/account")
#ApiOperation(value = "getAccount")
public void getAccount() {
//do something
}
But when I accessed this resource without logging in, I was successful.
What mistake am I doing? Or should I add something more? Like in the web.xml?
I found this repo very useful. https://github.com/silb/dropwizard-shiro/tree/release-0.2. I followed the instructions given in this. But there is one more thing I added in the configuration file.
#Valid
#JsonProperty("shiro-configuration")
public ShiroConfiguration shiro = new ShiroConfiguration();
Then in the resources class, I wrote login and logout as two services.
#POST
#Path("/session")
#Produces(MediaType.TEXT_PLAIN)
public String login(#FormParam("username") String username, #FormParam("password") String password, #Auth Subject subject) {
subject.login(new UsernamePasswordToken(username, password));
return username;
}
#PUT
#Path("/logout")
#Produces(MediaType.TEXT_PLAIN)
public String logout(#Auth Subject subject){
subject.logout();
return "Successfully logged out!";
}
And then I annotated the secured resources with #RequiresAuthentication annotation.