I want to implement AWS Cognito server side flow with spring boot. I don't quite understand what the flow should be. Should I use spring oauth along with it ?
Requirement is something like this.
As an admin create user and give access to these created users to use my API from API Gateway (Let's ignore API Gateway part and say we just need access token from cognito for now)
Here is what I think should happen if I use AWS cognito with spring oauth2
user hits localhost:8000/oauth/token - with basic authentication (username and password)
which will do an API call with user credentials. User receives the token and uses it however he/she needs it.
Is this flow secure ? Should I use spring oauth along ?
How to handle respond to auth challenge ? Should user pass new password for first time when calling my application API ?
#RestController
public class Oauth {
#PostMapping(path = "/oauth/token")
public AdminInitiateAuthResult token(#RequestHeader("username") String username, #RequestHeader("password") String password) {
AWSCognitoIdentityProvider provider = AWSCognitoIdentityProviderClientBuilder
.standard()
.withRegion(Regions.US_WEST_2)
.withCredentials(new AWSStaticCredentialsProvider()).build();
Map<String, String> authParams = new HashMap<>();
authParams.put("USERNAME", username);
authParams.put("PASSWORD", password);
AdminInitiateAuthRequest adminInitiateAuthRequest = new AdminInitiateAuthRequest()
.withClientId("{client-id}")
.withUserPoolId("{user-pool-id}")
.withAuthFlow(AuthFlowType.ADMIN_USER_PASSWORD_AUTH)
.withAuthParameters(authParams);
AdminInitiateAuthResult authResult = provider.adminInitiateAuth(adminInitiateAuthRequest);
return authResult.getAuthenticationResult().getIdToken();
}
}
Business requirement is quite simple there needs to be a pool of users (cognito in this case) who can get some kind of a token to access few APIs. I want to achieve this using spring boot, since the API is written using spring boot and also I use AWS Api Gateway
Should I use spring oauth along with it ?
No. Authorization is done by API Gateway.
API clients need to obtain token from Cognito (i.e. authenticate themselves there) before using API. There is no need to do anything on application (Spring) side.
Details are here.
If you want to implement authentication for API clients using Cognito, then see Cognito docs for examples and manuals.
FYI Application Load Balancer can be used to handle all authentication flow for API.
Related
Working on an Azure AD-based authentication using OAuth2 and its On-Behalf-Of authentication flow.
I am wondering how to actually check the token comparison between the initial token provided by the user and the final token being provided by the middle service principal to the third or other service principal.
My current approach is creating another endpoint inside my application #GetMapping("/otherSP") and then call it within my application(internal API call) like:
String token = webclient.get()
.uri(newServicePrincipalUri)
.attributes(clientRegistrationId("currentServicePrincipalId"))
.retrieve()
.bodyToMono(String.class)
.block();
The endpoint within is like:
#GetMapping("/otherSP")
public String getExchangeToken(#RegisteredOAuth2AuthorizedClient("otherSP-id")OAuth2AuthorizedClient oAuth2AuthorizedClient){
return oAuth2AuthorizedClient.getAccessToken().getTokenValue();
}
For the purpose of acquiring the JWT, this approach seems barbaric. Is there any better approach or proper approach on how to actually check it or obtain the exchanged token?
I have a controller method that has an argument OAuth2AuthorizedClient with annotation #RegisteredOAuth2AuthorizedClient.
ResponseEntity<String> getFoo(
#RegisteredOAuth2AuthorizedClient("custom") OAuth2AuthorizedClient client) {
OAuth2AccessToken token = client.getAccessToken();
....
}
In order to resolve this, spring look for OAuth token on OAuth2AuthorizedClientService which actually stores the previously authenticated tokens in memory.
Now, I have a scenario where I obtain JWT token from OAuth server outside of this spring resource server, and trying to authenticate this server by passing token using Authorization header.
But when spring trying to resolve OAuth2AuthorizedClient it is looking for token in-memory with the principle of JWT (which will obviously not found since token is not obtained on this server). Hence send new login redirection for new token.
Overall question would be, is it possible to resolve OAuth2AuthorizedClient with the JWT token (obtained ourside of the server) passed in Authorization header?
I am consuming a secured Restful Service that grants access through Basic Auth (Username and Password). I have successfully accessed the API service and consumed its API; however, I am still confused as to what is the right way to implement HTTP headers with Basic Auth. I would assume I should authenticate only once, but the way I have constructed my code, it looks like I need to authenticate API with each service method I create.
Should I create a helper method with the authentication and call it on each service?
If you are using Basic Auth you need to always include credentials with your request. In case of OAuth, tokens have expiry. In this case, a token caching mechanism for the duration of a little bit less than the expiration duration would do the trick.
The Basic Auth is a kind of no status authentication. That means the server wouldn't record. Every time you need to provide username and password with your request. Each request is equal to the Server.
For another authentication called OAuth, the first time you request with username and password, the server will return a token to the frontend, which has an expiration period. So, you request every time with the token through the filter, where checks the expiry of the token. If it's not expired, using the same token for requests, otherwise, making a request to get another token.
I have a Netflix Zuul server receiving all HTTP requests and forwarding them to my microservice.
The underlying microservice authenticates users through Facebook oauth API. I receive the user data from Facebook API and I authenticate the user programmatically:
public Authentication login(String username, String password) {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, password);
Authentication result = authenticationManager.authenticate(token);
SecurityContextHolder.getContext().setAuthentication(result);
return result;
}
With Zuul in front this doesn't work. I think it sets up the session in the microservice environment, but never extends it to Zuul. It works fine when requests go straight to microservice.
What I've done:
I cleared the sensitiveHeaders property in my application.properties:
zuul.routes.[SERVICE_NAME].sensitiveHeaders=, but it's meant to work the other way around I think.
How do I setup a session with Zuul?
Edit:
My Zuul configuration:
# Zuul proxy
zuul.add-host-header=true
zuul.routes.httpbin.path=/**
zuul.routes.httpbin.serviceId=httpbin
zuul.routes.httbin.sensitiveHeaders=
httpbin.ribbon.listOfServers=http://localhost:8090
ribbon.eureka.enabled=false
Generally all rest based framework provide authenticate.
But are there any framework/lib/pattern that helps to secure rest endpoint with following capability
Only a authenticated user with following roles can access a end point with only particular params.
Basically i am trying to prevent two user(with same roles) to view each other data by passing each other id in request urls
Yeah you should look at Apache Shiro it offers really good support role base/permission based authorization.
An example of how you can annotate an endpoint would be:
#RequiresRoles(value = "admin")
I'd recommend you to check the Instance-Level Access Control of this document.