Multiple SecurityScheme for swagger/open-api - java

I am facing a problem with the swagger UI 3 and the generated shcema.yml file
Currently, I have the configuration similar to this one:
#SecurityScheme(name = "security-oauth", type = SecuritySchemeType.OAUTH2,
flows = #OAuthFlows(
authorizationCode = #OAuthFlow(
authorizationUrl = "${authUrl}",
tokenUrl = "${tokenUrl}",
scopes = {}
)
)
)
This works as intended. Now, I want to add another #SecurityScheme so that I can also pass a cookie to the FE (an Angular App) and to get it back. However, the swagger UI and the generation for the schema.yml file fails.
#SecuritySchemes( {
#SecurityScheme(name = "security-oauth", type = SecuritySchemeType.OAUTH2,
flows = #OAuthFlows(
authorizationCode = #OAuthFlow(
authorizationUrl = "${authUrl}",
tokenUrl = "${tokenUrl}",
scopes = {}
)
)
)
}
)
With the annotation like this, the schema.yml is missing the secuirySchema part:
securitySchemes:
security-oauth:
type: oauth2
flows:
authorizationCode:
Am I missing something or is there a bug in the generation where it does not properly handle the #SecuritySchemes annotation?

Related

How do I use MSAL4J to acquire a token for a daemon?

I have a daemon written in Java and running on AWS.
It calls multiple Microsoft APIs using tokens based on client Id, client secret and tenant id for each of 100s of user accounts that I am supporting. All worked fine with MS Azure Active Directory Library for Java (ADAL4J). But that is going bye bye and so I am being forced over to MS Authentication Library for Java (MSAL4J).
Basically, I need to use a client id, secret and tenant to get an accessToken that is required for a MS API.
After much meandering through the examples (many of which compile), it seems that this is the closest code I can get to:
public static String getToken( String apiUrl,
String clientId,
String clientSecret,
String tenantId,
String authUrl ) {
String token = null ;
if ( !authUrl.endsWith("/")){
authUrl = authUrl + "/" ;
}
/*
NOTE: This is derived from the following:
https://learn.microsoft.com/en-us/azure/active-directory/develop/scenario-desktop-acquire-token?tabs=java
I simplified the code by taking out the SilentParameters support.
*/
// BAD: authUrl = authUrl + "organizations/";
// BAD: authUrl = "https://login.microsoftonline.com/" + tenantId + "/";
// BAD: authUrl = "https://login.microsoftonline.com/organizations/";
authUrl = "https://login.microsoftonline.com/organizations/" + tenantId + "/" ;
// BAD: Set<String> SCOPE = Collections.singleton("https://graph.microsoft.com/.default");
// BAD: Set<String> scope = Collections.singleton(clientId);
Set<String> scope = Collections.singleton("");
// Load token cache from file and initialize token cache aspect. The token cache will have
// dummy data, so the acquireTokenSilently call will fail.
ITokenCacheAccessAspect tokenCacheAspect = new TokenPersistence("");
PublicClientApplication pca;
try {
pca = PublicClientApplication
.builder(clientId)
.authority(authUrl)
.setTokenCacheAccessAspect(tokenCacheAspect)
.build();
} catch (MalformedURLException e) {
return null ;
}
IAuthenticationResult result;
/*
BAD: ClientCredentialParameters parameters =
BAD: ClientCredentialParameters
BAD: .builder(SCOPE)
BAD: .build();
*/
UserNamePasswordParameters parameters =
UserNamePasswordParameters
.builder(scope, clientId, clientSecret.toCharArray())
.build();
result = pca.acquireToken(parameters).join();
token = result.accessToken() ;
return token ;
}
So, it compiles (even the BAD commented out code compiles), and it runs but it generates:
com.microsoft.aad.msal4j.MsalClientException: com.fasterxml.jackson.databind.JsonMappingException: No suitable constructor found for type [simple type, class com.microsoft.aad.msal4j.InstanceDiscoveryMetadataEntry]: can not instantiate from JSON object (missing default constructor or creator, or perhaps need to add/enable type information?)
The above is generated on the acquireToken call (near the bottom).
I can't figure out what code needs a default constructor (to make the JSON happy).
OTOH, I don't know if these are the calls that I should even be making; there seem to be about 47 different ways through and around this MSAL stuff and I am not at ALL sure if I have found "the right path".
Help Me, Obi-Wan Kenobi. You're My Only Hope!
Checkout the ms-identity-java-daemon sample: https://github.com/Azure-Samples/ms-identity-java-daemon.
Try not using TokenCacheAccessAspect at all and see if that works? I.e. something like:
IClientCredential credential = ClientCredentialFactory.createFromSecret(clientSecret);
ConfidentialClientApplication cca = ConfidentialClientApplication.builder(clientId, credential)
.authority(authUrl)
.build();
Set<String> scope = ImmutableSet.of();
ClientCredentialParameters parameters =
ClientCredentialParameters.builder(scope)
.build();
result = cca.acquireToken(parameters).join();
Where authUrl should look like https://login.microsoftonline.com/<tenantId>
See: https://learn.microsoft.com/en-us/azure/active-directory/develop/scenario-daemon-acquire-token?tabs=java

AWS SSM parameter store not fetching all key/values

Could someone let me know why the below code only fetching few entries from the parameter store ?
GetParametersByPathRequest getParametersByPathRequest = new GetParametersByPathRequest();
getParametersByPathRequest.withPath("/").setRecursive(true);
getParametersByPathRequest.setWithDecryption(true);
GetParametersByPathResult result = client.getParametersByPath(getParametersByPathRequest);
result.getParameters().forEach(parameter -> {
System.out.println(parameter.getName() + " - > " + parameter.getValue());
});
GetParametersByPath is a paged operation. After each call you must retrieve NextToken from the result object, and if it's not null and not empty you must make another call with it added to the request.
Here's an example using DescribeParameters, which has the same behavior:
DescribeParametersRequest request = new DescribeParametersRequest();
DescribeParametersResult response;
do
{
response = client.describeParameters(request);
for (ParameterMetadata param : response.getParameters())
{
// do something with metadata
}
request.setNextToken(response.getNextToken());
}
while ((response.getNextToken() != null) && ! respose.getNextToken.isEmpty());
Here is the code, based on the code above, for the new 2.0 version of AWS SSM manager. Notice I have set the maxResults to 1 to prove out the loop. You will want to remove that. AWS has mentioned that in the new code they wanted to emphasize immutability.
Using this dependency:
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>ssm</artifactId>
<version>2.10.32</version>
</dependency>
I came up with this code:
private void refreshCache() {
StopWatch sw = StopWatch.createStarted();
GetParametersByPathRequest request = GetParametersByPathRequest.builder()
.path(prefix)
.withDecryption(useDecryption)
.maxResults(1)
.build();
GetParametersByPathResponse response;
do {
response = ssm.getParametersByPath(request);
for (Parameter p : response.parameters()) {
//do something with the values.
}
request = GetParametersByPathRequest.builder()
.path(prefix)
.withDecryption(useDecryption)
.nextToken(response.nextToken())
.maxResults(1)
.build();
}
while (StringUtils.isNotBlank(response.nextToken()));
LOG.trace("Refreshed parameters in {}ms", sw.getTime());
}
private void getSsmParams() {
AWSSimpleSystemsManagement client = AWSSimpleSystemsManagementClientBuilder.defaultClient();
GetParametersByPathRequest request = new GetParametersByPathRequest();
request.withRecursive(true);
request.withPath('/your/path/parameterName').setWithDecryption(true);
GetParametersByPathResult response;
do {
response = client.getParametersByPath(request);
for (Parameter p : response.parameters()) {
//do something with the values. maybe add to a list
}
request.setNextToken(response.getNextToken())
}
while (StringUtils.isNotBlank(response.getNextToken()));
}
Above piece of code worked for me .ssm only sends 10 parameters at a time, so if you want to fetch more than 10 parameters from ssm parameter store programatically you will have to use multiple calls to fetch them. here the token is important , if there are more values in the path (request.withPath('/your/path/parameterName')) you have given, it will send a token indicating that there are more values in the given path ,and you will have to make the following request with the token received from the previous request in order to get the rest of the values.

Add AWS SQS Permission to all Principals through SDK

I'm trying to create an AWS SQS queue through the Java SDK, and then add all permissions for all users. I can create the queue fine, but I'm struggling to know what value I can pass in for the Principals. This is what my code looks like:
CreateQueueRequest createQueueRequest = new CreateQueueRequest(queueName).withAttributes(attributes);
CreateQueueResult createQueueResult = amazonSqs.createQueue(createQueueRequest);
String queueUrl = createQueueResult.getQueueUrl();
amazonSqs.addPermission(queueUrl, "*", ????, Arrays.asList("*"));
The ??? is what I'm not sure on. I've tried Arrays.asList("*") but it complains about it not being valid. In the web console, there is a checkbox for Everyone, and I'm just wanting to do the same thing in the SDK. Is there some value I can pass for this?
--- UPDATE ---
I've been able to accomplish this another way through a Policy:
String queueUrl = createQueueResult.getQueueUrl();
GetQueueAttributesResult getQueueAttributesResult = amazonSqs.getQueueAttributes(queueUrl, Arrays.asList(QUEUE_ARN_ATTRIBUTE_NAME));
String queueArn = getQueueAttributesResult.getAttributes().get(QUEUE_ARN_ATTRIBUTE_NAME);
if (needToSetPolicy)
{
Policy allAccessPolicy = new Policy("SQSAllAccess", Arrays.asList(
new Statement(Effect.Allow)
.withActions(() -> "SQS:*")
.withPrincipals(Principal.All)
.withId("SQSAllAccessStatement")
.withResources(new Resource(queueArn))
));
Map<String, String> policyMap = new HashMap<>(1);
policyMap.put(POLICY_ATTRIBUTE_NAME, allAccessPolicy.toJson());
amazonSqs.setQueueAttributes(queueUrl, policyMap);
}
It seems like there should be a better/easier way to do this. Are there any better/cleaner/easier ways of doing this?
In kotlin using the constants from the SDK
val policy: Policy = Policy("AllowAllSendMessage", listOf(Statement(Effect.Allow)
.withActions(SQSActions.SendMessage)
.withPrincipals(Principal.All)
.withId("AllowAllSendMessage")
.withResources(Resource(queueArn))))
_sqs.setQueueAttributes(SetQueueAttributesRequest()
.withQueueUrl(queueUrl)
.withAttributes(mapOf(QueueAttributeName.Policy.toString() to policy.toJson())))

How to extract parameters from an object to show in parameters in documentation

I have the following API endpoint:
#ApiResponses(
value = {
#ApiResponse(code = 200, message = "OK",
responseHeaders = {
#ResponseHeader(name = "X-RateLimit-Limit", description = "The defined maximum number of requests available to the consumer for this API.", response = Integer.class),
#ResponseHeader(name = "X-RateLimit-Remaining", description = "The number of calls remaining before the limit is enforced and requests are bounced.", response = Integer.class),
#ResponseHeader(name = "X-RateLimit-Reset", description = "The time, in seconds, until the limit expires and another request will be allowed in. This header will only be present if the limit is being enforced.", response = Integer.class)
}
)
}
)
#ApiOperation(httpMethod = "GET", hidden = false, nickname = "Get Network Availability in JSON", value = "Get network availability for a product", response = AvailableToPromise.class, position = 1)
#RequestMapping(value = "/{product_id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> networkAvailabilityJsonResponse(
#RequestHeader HttpHeaders headers,
#PathVariable("product_id") String productId,
#Valid NetworkAvailabilityCmd cmd, //query params
BindingResult result)
throws Exception {}
}
Certain parameters, such as key are taken from the query and mapped into this object through Spring MVC.
However, in the parameters section of my endpoint in the swagger-ui, it's showing me a few odd things:
None of the variables that are in NetworkAvailabilityCmd show in this parameters list, and cmd itself shows as being located in the request body (it's actually located in the query). Is there a way to hide cmd and extract the params inside this object to show on the params list? I'd like the params list to look like this (with more params):
I'm able to do this if I use #ApiImplicitParams on the method endpoint, and write out each of the params. However, this NetworkAvailabilityCmd is used for many endpoints, and having the list of params on each endpoint is very messy. Being able to extract the variables from in the object would be far cleaner, and would prevent people from forgetting to add the entire list to new endpoints.
I imagine that it requires an annotation on NetworkAvailabilityCmd cmd, and potentially something on the variables in that class, but I can't seem to find what I'm looking for in the docs.
Thanks!
I found out that adding #ModelAttribute worked magically. This annotation is from Spring.

Why is SocialAuth saying "facebook is not a provider or valid OpenId URL"?

Using SocialAuth: v2.3 via Railo CFML Engine, I am getting the following exception thrown:
Railo 3.3.4.003 Error (org.brickred.socialauth.exception.SocialAuthException)
Message facebook is not a provider or valid OpenId URL
Cause org.brickred.socialauth.exception.SocialAuthException
Stacktrace The Error Occurred in
/Users/rountrjf/Sites/ccpd-dev/controllers/socialauth.cfc: line 31
29: manager.setSocialAuthConfig(config);
30: successUrl = "http://dev.ccpd.uc.edu/socialauth/success";
31: providerUrl = manager.getAuthenticationUrl("facebook", successUrl);
Here is a snippet of my CFC code:
public string function login() {
id = params.key;
configFile = expandPath("/SocialAuth/oauth_config.properties");
inputFile = createObject("java","java.io.File").init(configFile);
inputStream = createObject("java", "java.io.FileInputStream").init(inputFile);
SocialAuthConfig = createObject("java","org.brickred.socialauth.SocialAuthConfig").init();
config = SocialAuthConfig.getDefault();
config.load(configFile);
SocialAuthManager = createObject("java","org.brickred.socialauth.SocialAuthManager").init();
manager = SocialAuthManager;
manager.setSocialAuthConfig(config);
successUrl = "http://dev.ccpd.uc.edu/socialauth/success";
providerUrl = manager.getAuthenticationUrl("facebook", successUrl);
Why is it throwing this error? The "configFile" has a property for "facebook" and it configured as shown in step 3 of the "Getting Started" guide.
CONFIG FILE I'M USING
#google
www.google.com.consumer_key = opensource.brickred.com
www.google.com.consumer_secret = YC06FqhmCLWvtBg/O4W/aJfj
#you can set custom permission by using custom_permissions with provider prefix.
#www.google.com.custom_permissions = http://www.google.com/m8/feeds/,http://picasaweb.google.com/data/
#yahoo
api.login.yahoo.com.consumer_key = dj0yJmk9VTdaSUVTU3RrWlRzJmQ9WVdrOWNtSjZNMFpITm1VbWNHbzlNQS0tJnM9Y29uc3VtZXJzZWNyZXQmeD1iMA--
api.login.yahoo.com.consumer_secret = 1db3d0b897dac60e151aa9e2499fcb2a6b474546
#twitter
twitter.com.consumer_key = E3hm7J9IQbWLijpiQG7W8Q
twitter.com.consumer_secret = SGKNuXyybt0iDdgsuzVbFHOaemV7V6pr0wKwbaT2MH0
#facebook
graph.facebook.com.consumer_key = 152190004803645
graph.facebook.com.consumer_secret = 64c94bd02180b0ade85889b44b2ba7c4
#you can set custom permission by using custom_permissions with provider prefix.
#graph.facebook.com.custom_permission = publish_stream,email,user_birthday,user_location,offline_access
#hotmail
consent.live.com.consumer_key = 000000004403D60E
consent.live.com.consumer_secret = cYqlii67pTvgPD4pdB7NUVC7L4MIHCcs
#AOL
api.screenname.aol.com.consumer_key = ab1QxoYXlT-x-ARL
api.screenname.aol.com.consumer_secret = 000
#LinkedIn
api.linkedin.com.consumer_key = 9-mmqg28fpMocVuAg87exH-RXKs70yms52GSFIqkZN25S3m96kdPGBbuSxdSBIyL
api.linkedin.com.consumer_secret = e6NBqhDYE1fX17RwYGW5vMp25Cvh7Sbw9t-zMYTIW_T5LytY5OwJ12snh_YftgE4
#MySpace
api.myspace.com.consumer_key = 29db395f5ee8426bb90b1db65c91c956
api.myspace.com.consumer_secret = 0fdccc829c474e42867e16b68cda37a4c4b7b08eda574fe6a959943e3e9be709
#FourSquare
foursquare.com.consumer_key = JQKEM1PHWFW4YF2YPEQBRRESXE3SBGNCYJWWDTZKF3IZNJ3V
foursquare.com.consumer_secret = 4IILLDFDVPP2LC554S4KXKETQNTDKPDSEVCKVHA2QEHKYBEQ
#Yammer
www.yammer.com.consumer_key=5zyIkp12TrkulSRbSegQ
www.yammer.com.consumer_secret=zUcCB9kqWhI1IiTAJbl9QdG2AWcUJMDWp3Qyv5VJJw
#Mendeley
api.mendeley.com.consumer_key=f31077a7576d5e02537e232eb649403c04fce1dd0
api.mendeley.com.consumer_secret=1810bc92d4625f673e4ff35cb248aab3
#Salesforce
login.salesforce.com.consumer_key = 3MVG9Y6d_Btp4xp4yFMR0tPSndkAVu4OBejuYcL2iGFC68tA49PknWKX20XdPl5s1iwWldyuAbSINWHbB2Jcu
login.salesforce.com.consumer_secret = 1993703471433041656
I would suggest using Constants.FACEBOOK which is actually "facebook" but in case it isn't it has a value that should work.
A possible reason that the error appears is that you are not using the correct input file.
Make sure that the configuration config is loaded correctly,
try to call config.getProviderConfig(Constants.FACEBOOK) and see if it returns null
Lastly you can try this. This is what I used and works.
SocialAuthConfig config = new SocialAuthConfig();
SocialAuthManager socialAuthManager = new SocialAuthManager();
config.load(inputStream);
socialAuthManager.setSocialAuthConfig(config);
I don't really know Railo CFML Engine and what it does so I can't help.
Maybe remove .getDefault() from config = SocialAuthConfig.getDefault();?

Categories

Resources