Spring doc openapi oauth2 resource server not working - spring-boot

Although I have successfully authorize but when I get api 401 is there any way to fix it.
Authorize swagger
Execute api swageer
Swagger config application.yml
springdoc:
version: 'v1.0'
swagger-ui:
oauth:
use-basic-authentication-with-access-code-grant: true
use-pkce-with-authorization-code-grant: true
client-id: USER_CLIENT_APP
client-secret: password
oAuthFlow:
authorizationUrl: ${OAUTH2_SERVER:http://localhost:8080}/oauth/authorize
tokenUrl: ${OAUTH2_SERVER:http://localhost:8080}/oauth/token
OpenApiConfig.class
#OpenAPIDefinition(info = #Info(title = "User",
description = "description", version = "v1"))
#SecurityScheme(name = "security_auth", type = SecuritySchemeType.OAUTH2,
flows = #OAuthFlows(password = #OAuthFlow(
authorizationUrl = "${springdoc.oAuthFlow.authorizationUrl}",
tokenUrl = "${springdoc.oAuthFlow.tokenUrl}",
scopes = {
#OAuthScope(name = "trust", description = "trust scope"),
#OAuthScope(name = "read", description = "read scope"),
#OAuthScope(name = "write", description = "write scope")
})))
public class OpenApiConfig {}
get token
post-man get /oauth/token
I want to access oauth2 in springdoc openapi.

Related

Configuring Swagger UI for OAuth 2.0 in Spring Boot with Kotlin

I am trying to configure OpenAPI 3 for OAuth 2.0 with a configuration class in Spring Boot with Kotlin.
Even though I set oauth2RedirectUrl in application.yml, when I click authorize in swagger UI to get new token to send a request, redirect url doesn't work as expected and I get the default redirect url called something like that(I believe it's a default redirectUrl): &redirect_uri=http://localhost:8080/oauth2-redirect.html instead of (what i configured in application.yaml)
Access the Swagger-UI at http://localhost:8080/swagger-ui/index.html?queryConfigEnabled=true&url=/v3/api-docs
Then click the authorize button and use the preconfigured values.
The IdentityProviderController prints then the configured values, e.g. redirect_uri.
The redirect_uri looks like http://localhost:8080/swagger-ui/oauth2-redirect.html and the swagger-ui:oauth2RedirectUrl path is missing. Even when it is configured in the application.yaml.
I added the following dependencies:
implementation("org.springdoc:springdoc-openapi-ui:1.6.14")
implementation("org.springdoc:springdoc-openapi-kotlin:1.6.14")
implementation("org.springdoc:springdoc-openapi-security:1.6.14")
and this is my application.yml
springdoc:
api-docs:
enabled: true
swagger-ui:
query-config-enabled: true
oauth:
client-id: <clientId>
client-secret: <clientSecret>
use-pkce-with-authorization-code-grant: true
oauth2RedirectUrl: <redirectUrl>
and this here is my configuration class:
#Configuration
#OpenAPIDefinition
#SecurityScheme(
name = "oauth2",
type = SecuritySchemeType.OAUTH2,
flows =
OAuthFlows(
authorizationCode =
OAuthFlow(
authorizationUrl = "<authorizationUrl>",
tokenUrl = "<tokenUrl>",
scopes =
[
OAuthScope(name = "test1"),
OAuthScope(name = "test2"),
OAuthScope(name = "test3")],
)))
open class OpenApiConfiguration {
#Bean
open fun customOpenAPI(): OpenAPI {
return OpenAPI()
.components(Components())
.info(
Info()
.title("ABC Service Rest API")
.description("description...")
.version("1.0.0"))
}
}
What am I missing here?
UPDATE: (17.02.2023)
After I am changing the redirect_uri in chrome with the correct one, then I can reach the Identity proverders' page, so I only need to find a way to set my redirectUrl configuration properly.

Lambda Web API returning 403 for verbs other than POST

I have created a Serverless Lambda Web API using a built-in template. The web api is deployed to AWS using CloudFormation and everything is working fine (i.e. All GET, POST etc).
I have then checked the resources created by CloudFormation and created all of the resources using Terraform. I have double checked and REST API in the API Gateway, Lambda, Lambda permissions and triggers are exactly the same when created from both serverless template and terraform scripts.
The issue is the when using the resources created from Terraform, I am not able to call the Web API using HTTP verb other then POST. Below is my terraform script for the API Gateway.
resource "aws_api_gateway_rest_api" "SimulationServer_api_gateway_rest" {
name = "SimulationServer"
description = "Terraform Serverless Application Example"
}
resource "aws_api_gateway_resource" "api_gw_proxy_resource" {
rest_api_id = aws_api_gateway_rest_api.SimulationServer_api_gateway_rest.id
parent_id = aws_api_gateway_rest_api.SimulationServer_api_gateway_rest.root_resource_id
path_part = "{proxy+}"
}
resource "aws_api_gateway_method" "api_gw_proxy_method" {
rest_api_id = aws_api_gateway_rest_api.SimulationServer_api_gateway_rest.id
resource_id = aws_api_gateway_resource.api_gw_proxy_resource.id
http_method = "ANY"
authorization = "NONE"
}
resource "aws_api_gateway_integration" "api_gw_proxy_integration" {
rest_api_id = aws_api_gateway_rest_api.SimulationServer_api_gateway_rest.id
resource_id = aws_api_gateway_method.api_gw_proxy_method.resource_id
http_method = aws_api_gateway_method.api_gw_proxy_method.http_method
integration_http_method = "ANY"
type = "AWS_PROXY"
uri = aws_lambda_function.SimulationServer.invoke_arn
}
resource "aws_api_gateway_method" "api_gw_proxy_root_method" {
rest_api_id = aws_api_gateway_rest_api.SimulationServer_api_gateway_rest.id
resource_id =
aws_api_gateway_rest_api.SimulationServer_api_gateway_rest.root_resource_id
http_method = "ANY"
authorization = "NONE"
}
resource "aws_api_gateway_integration" "api_gw_proxy_root_integration" {
rest_api_id = aws_api_gateway_rest_api.SimulationServer_api_gateway_rest.id
resource_id = aws_api_gateway_method.api_gw_proxy_root_method.resource_id
http_method = aws_api_gateway_method.api_gw_proxy_root_method.http_method
integration_http_method = "ANY"
type = "AWS_PROXY"
uri = aws_lambda_function.SimulationServer.invoke_arn
}
resource "aws_api_gateway_deployment" "api_gw_deployment" {
depends_on = [
aws_api_gateway_integration.api_gw_proxy_integration,
aws_api_gateway_integration.api_gw_proxy_root_integration,
]
rest_api_id = aws_api_gateway_rest_api.SimulationServer_api_gateway_rest.id
stage_name = var.env
}
output "base_url" {
value = aws_api_gateway_deployment.api_gw_deployment.invoke_url
}
It turned out to be very strange but simple solution.
Instead of using,
integration_http_method = "ANY"
When I used,
integration_http_method = "POST"
Then it started working for all HTTP Verbs (GET, POST, PUT etc)

Terraform API Gateway for use with Lambda Proxy Integration

I've spent the day fighting with API Gateway and AWS Serverless Express to no avail. My goal is to deploy an API Gateway, via Terraform (v0.12), that proxies all requests to an AWS Serverless Express based lambda. The connection between API Gateway and Lambda seems to exist, but tenuous, as any invocation (from API Gateway console or Postman) respond with 502 Bad Gateway, apparently due to timeout (so states the lambda CloudWatch logs). It does not appear that the lambda code actually runs, only that it spins up ineffectually.
The API Gateway and Lambda should support path parameters and query strings:
GET /some/path/:id get by id
GET /some/path?query=param get
collection
POST /some/path create resource
PATCH /some/path/:id update resource
DELETE /some/path/:id remove resource
After several false starts, I've tried to make the API Gateway Terraform module as flexible as possible:
resource "aws_api_gateway_rest_api" "rest_api" {
name = "${var.application_name} API"
description = var.description
}
resource "aws_api_gateway_resource" "proxy" {
rest_api_id = aws_api_gateway_rest_api.rest_api.id
parent_id = aws_api_gateway_rest_api.rest_api.root_resource_id # aws_api_gateway_resource.version.id
path_part = "{proxy+}"
}
resource "aws_api_gateway_method" "method" {
rest_api_id = aws_api_gateway_rest_api.rest_api.id
resource_id = aws_api_gateway_resource.proxy.id
http_method = "ANY"
authorization = "NONE"
request_parameters = {
"method.request.path.proxy" = true
}
}
resource "aws_api_gateway_integration" "integration" {
rest_api_id = aws_api_gateway_rest_api.rest_api.id
resource_id = aws_api_gateway_resource.proxy.id
http_method = aws_api_gateway_method.method.http_method
integration_http_method = "POST"
type = "AWS_PROXY"
uri = "arn:aws:apigateway:${local.region}:lambda:path/2015-03-31/functions/${var.lambda_arn}/invocations"
}
resource "aws_api_gateway_deployment" "apig_deployment" {
depends_on = [
"aws_api_gateway_resource.proxy",
"aws_api_gateway_method.method",
"aws_api_gateway_integration.integration"
]
rest_api_id = aws_api_gateway_rest_api.rest_api.id
stage_name = var.api_stage_name
lifecycle {
create_before_destroy = true
}
}
resource "aws_lambda_permission" "apig_to_lambda" {
statement_id = "AllowExecutionFromAPIGateway"
action = "lambda:InvokeFunction"
function_name = var.function_name
principal = "apigateway.amazonaws.com"
source_arn = "arn:aws:execute-api:${local.region}:${local.account_id}:${aws_api_gateway_rest_api.rest_api.id}/*/*/*" # TODO: lock this down
}
You are getting 502 error that indicates that the response received by api gateway is not proper.
Having said that your application seems to return json response. Can you try below/confirm the settings?
Add the correct binary mime types in your lambda configuration. See here for more details.
Allow the same mime types or wildcard on api gateway side as below.
resource "aws_api_gateway_rest_api" "rest_api" {
name = "${var.application_name} API"
description = var.description
// Wildcard mimes, accept any
binary_media_types = ["*/*"]
}

Retrieve #Authorization swagger codegen java

I work with swagger 2.0 to define a back end and trying to define security.
I end up with :
---
swagger: "2.0"
info:
version: 1.0.0
title: Foo test
schemes:
- https
paths:
/foo:
get:
security:
- Foo: []
responses:
200:
description: Ok
securityDefinitions:
Foo:
type: apiKey
name: X-BAR
in: header
Everything good till now, java codegen give me :
#ApiOperation(value = "", nickname = "fooGet", notes = "", authorizations = {
#Authorization(value = "Foo")
}, tags={ })
#ApiResponses(value = {
#ApiResponse(code = 200, message = "Ok") })
#RequestMapping(value = "/foo",
method = RequestMethod.GET)
default ResponseEntity<Void> fooGet() {
if(getObjectMapper().isPresent() && getAcceptHeader().isPresent()) {
} else {
log.warn("ObjectMapper or HttpServletRequest not configured in default FooApi interface so no example is generated");
}
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
}
I'm wondering, in the interface, how to retrieve "properly" the X-BAR header value.
I end up with :
#Autowired
private HttpServletRequest httpServletRequest;
httpServletRequest.getHeader("X-BAR")
which works , but is there a more proper way ?
Define a class "Foo" ? a doFilter ?
Thanks

Grails spring security oauth2 provider request for resource with correct bearer token redirects to login

As the title implies, I have a controller method protected by the oAuth2 plugin, but when I send a request to it including a correct Authorization: Bearer <token> (using Postman), the response I get is the HTML for the login page.
Method in question:
#Secured(["ROLE_USER", "#oauth2.clientHasAnyRole('ROLE_CLIENT', 'ROLE_TRUSTED_CLIENT')"])
def getUserData(){
response.setContentType("application/json")
User u = springSecurityService.currentUser
println u
render u.mseUserInfo
}
Config.groovy:
// Added by the Spring Security Core plugin:
grails.plugin.springsecurity.auth.loginFormUrl = '/mse/login'
grails.plugin.springsecurity.userLookup.userDomainClassName = 'cz.improvisio.MSEauthProvider.user.User'
grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'cz.improvisio.MSEauthProvider.user.UserRole'
grails.plugin.springsecurity.authority.className = 'cz.improvisio.MSEauthProvider.user.Role'
grails.plugin.springsecurity.controllerAnnotations.staticRules = [
'/oauth/authorize.dispatch':[
"ROLE_USER",
"isFullyAuthenticated()"
],
'/oauth/token.dispatch':[
"ROLE_USER",
"isFullyAuthenticated()"
],
'/mse/login':["permitAll"],
'/mse/':["permitAll"],
'/**':["permitAll"]]
// Added by the Spring Security OAuth2 Provider plugin:
grails.plugin.springsecurity.oauthProvider.clientLookup.className = 'cz.improvisio.MSEauthProvider.user.Client'
grails.plugin.springsecurity.oauthProvider.authorizationCodeLookup.className = 'cz.improvisio.MSEauthProvider.user.AuthCode'
grails.plugin.springsecurity.oauthProvider.accessTokenLookup.className = 'cz.improvisio.MSEauthProvider.user.AccessToken'
grails.plugin.springsecurity.oauthProvider.refreshTokenLookup.className = 'cz.improvisio.MSEauthProvider.user.RefreshToken'
grails.plugin.springsecurity.filterChain.chainMap = [
'/oauth/token': 'JOINED_FILTERS,-oauth2ProviderFilter,-securityContextPersistenceFilter,-logoutFilter,-authenticationProcessingFilter,-rememberMeAuthenticationFilter,-exceptionTranslationFilter',
'/securedOAuth2Resources/**': 'JOINED_FILTERS,-securityContextPersistenceFilter,-logoutFilter,-authenticationProcessingFilter,-rememberMeAuthenticationFilter,-oauth2BasicAuthenticationFilter,-exceptionTranslationFilter',
'/**': 'JOINED_FILTERS,-statelessSecurityContextPersistenceFilter,-oauth2ProviderFilter,-clientCredentialsTokenEndpointFilter,-oauth2BasicAuthenticationFilter,-oauth2ExceptionTranslationFilter'
]
This is the client creation from Bootstrap.groovy:
new Client(
clientId: 'testClient',
authorizedGrantTypes: [
'authorization_code',
'refresh_token',
'implicit',
'password',
'client_credentials'
],
authorities: ['ROLE_CLIENT'],
scopes: ['read', 'write'],
redirectUris: ['http://test.com']).save(flush: true)
And one more slightly related question: I couldnt find a way to get the User to whose resources the access token should be linked to, so I assumed Id be able to get it through springSecurityService. Is this the correct way of doing so? Or do I need to pass the userId to the method (and will OpenAM do it?)?
Turns out I didnt have the proper filter chain set up for my action. Changing config to
grails.plugin.springsecurity.filterChain.chainMap = [
'/oauth/token': 'JOINED_FILTERS,-oauth2ProviderFilter,-securityContextPersistenceFilter,-logoutFilter,-authenticationProcessingFilter,-rememberMeAuthenticationFilter,-exceptionTranslationFilter',
'/securedOAuth2Resources/**': 'JOINED_FILTERS,-securityContextPersistenceFilter,-logoutFilter,-authenticationProcessingFilter,-rememberMeAuthenticationFilter,-oauth2BasicAuthenticationFilter,-exceptionTranslationFilter',
'/myController/getUserData': 'JOINED_FILTERS,-securityContextPersistenceFilter,-logoutFilter,-authenticationProcessingFilter,-rememberMeAuthenticationFilter,-oauth2BasicAuthenticationFilter,-exceptionTranslationFilter',
'/**': 'JOINED_FILTERS,-statelessSecurityContextPersistenceFilter,-oauth2ProviderFilter,-clientCredentialsTokenEndpointFilter,-oauth2BasicAuthenticationFilter,-oauth2ExceptionTranslationFilter'
]
fixed it.

Resources