4040import com .google .common .base .CaseFormat ;
4141import com .google .common .base .Converter ;
4242import com .google .common .base .Function ;
43+ import com .google .common .base .Joiner ;
4344import com .google .common .collect .FluentIterable ;
4445import com .google .common .collect .ImmutableList ;
4546import com .google .common .collect .ImmutableListMultimap ;
4647import com .google .common .collect .ImmutableMap ;
48+ import com .google .common .collect .ImmutableSet ;
4749import com .google .common .collect .Lists ;
4850import com .google .common .collect .Maps ;
4951import com .google .common .reflect .TypeToken ;
9395 * Generates a {@link Swagger} object representing a set of {@link ApiConfig} objects.
9496 */
9597public class SwaggerGenerator {
98+ private static final Joiner COMMA_JOINER = Joiner .on (',' );
9699 private static final String API_KEY = "api_key" ;
97100 private static final String API_KEY_PARAM = "key" ;
98101 private static final String MANAGEMENT_DEFINITIONS_KEY = "x-google-management" ;
@@ -238,14 +241,6 @@ private void writeApi(ApiKey apiKey, ImmutableList<? extends ApiConfig> apiConfi
238241 // TODO: This may result in duplicate validations in the future if made available online
239242 genCtx .validator .validate (apiConfigs );
240243 for (ApiConfig apiConfig : apiConfigs ) {
241- for (IssuerConfig issuerConfig : apiConfig .getIssuers ().asMap ().values ()) {
242- addNonConflictingSecurityDefinition (swagger , issuerConfig );
243- }
244- List <String > legacyAudiences = apiConfig .getApiClassConfig ().getAudiences ();
245- if (legacyAudiences != null && !legacyAudiences .isEmpty ()) {
246- addNonConflictingSecurityDefinition (swagger , ApiIssuerConfigs .GOOGLE_ID_TOKEN_ISSUER );
247- addNonConflictingSecurityDefinition (swagger , ApiIssuerConfigs .GOOGLE_ID_TOKEN_ISSUER_ALT );
248- }
249244 for (ApiLimitMetricConfig limitMetric : apiConfig .getApiLimitMetrics ()) {
250245 addNonConflictingApiLimitMetric (genCtx .limitMetrics , limitMetric );
251246 }
@@ -343,7 +338,7 @@ private void writeApiMethod(
343338 response .setSchema (new RefProperty (schema .name ()));
344339 }
345340 operation .response (200 , response );
346- writeAudiences (swagger , methodConfig , genCtx . writeInternal , operation );
341+ writeAuthConfig (swagger , methodConfig , operation );
347342 if (methodConfig .isApiKeyRequired ()) {
348343 operation .addSecurity (API_KEY , ImmutableList .<String >of ());
349344 Map <String , SecuritySchemeDefinition > definitions = swagger .getSecurityDefinitions ();
@@ -355,44 +350,31 @@ private void writeApiMethod(
355350 addDefinedMetricCosts (genCtx .limitMetrics , operation , methodConfig .getMetricCosts ());
356351 }
357352
358- private void writeAudiences (Swagger swagger , ApiMethodConfig methodConfig , boolean writeInternal ,
359- Operation operation ) throws ApiConfigException {
353+ private void writeAuthConfig (Swagger swagger , ApiMethodConfig methodConfig , Operation operation )
354+ throws ApiConfigException {
360355 ApiIssuerAudienceConfig issuerAudiences = methodConfig .getIssuerAudiences ();
361356 boolean issuerAudiencesIsEmpty = !issuerAudiences .isSpecified () || issuerAudiences .isEmpty ();
362357 List <String > legacyAudiences = methodConfig .getAudiences ();
363358 boolean legacyAudiencesIsEmpty = legacyAudiences == null || legacyAudiences .isEmpty ();
364359 if (issuerAudiencesIsEmpty && legacyAudiencesIsEmpty ) {
365360 return ;
366361 }
367- ImmutableMap <String , Collection <String >> audiences = issuerAudiences .asMap ();
368- // For reversability purposes, we can't use helper data structures here. When Swagger reads
369- // the document back in, it uses primitive data structures.
370- ImmutableList .Builder <ImmutableMap <String , ImmutableMap <String , List <String >>>> xSecurity =
371- ImmutableList .builder ();
372362 if (!issuerAudiencesIsEmpty ) {
373- for (Map . Entry < String , Collection < String >> entry : audiences . entrySet ()) {
374- operation . addSecurity ( entry . getKey (), ImmutableList . <String >of () );
375- if ( writeInternal ) {
376- xSecurity . add ( ImmutableMap . of ( entry . getKey (), createAudiences ( entry . getValue ())) );
377- }
363+ for (String issuer : issuerAudiences . getIssuerNames ()) {
364+ ImmutableSet <String > audiences = issuerAudiences . getAudiences ( issuer );
365+ IssuerConfig issuerConfig = methodConfig . getApiConfig (). getIssuers (). getIssuer ( issuer );
366+ String fullIssuer = addNonConflictingSecurityDefinition ( swagger , issuerConfig , audiences );
367+ operation . addSecurity ( fullIssuer , ImmutableList .< String > of ());
378368 }
379369 }
380370 if (!legacyAudiencesIsEmpty ) {
381- addNonConflictingSecurityDefinition (swagger , ApiIssuerConfigs .GOOGLE_ID_TOKEN_ISSUER );
382- addNonConflictingSecurityDefinition (swagger , ApiIssuerConfigs .GOOGLE_ID_TOKEN_ISSUER_ALT );
383- operation .addSecurity (Constant .GOOGLE_ID_TOKEN_NAME , ImmutableList .<String >of ());
384- operation .addSecurity (Constant .GOOGLE_ID_TOKEN_NAME_HTTPS , ImmutableList .<String >of ());
385- if (writeInternal ) {
386- ImmutableMap <String , List <String >> legacySwaggerAudiences =
387- createAudiences (legacyAudiences );
388- xSecurity .add (
389- ImmutableMap .of (Constant .GOOGLE_ID_TOKEN_NAME , legacySwaggerAudiences ));
390- xSecurity .add (
391- ImmutableMap .of (Constant .GOOGLE_ID_TOKEN_NAME_HTTPS , legacySwaggerAudiences ));
392- }
393- }
394- if (writeInternal ) {
395- operation .setVendorExtension ("x-security" , xSecurity .build ());
371+ ImmutableSet <String > legacyAudienceSet = ImmutableSet .copyOf (legacyAudiences );
372+ String fullIssuer = addNonConflictingSecurityDefinition (
373+ swagger , ApiIssuerConfigs .GOOGLE_ID_TOKEN_ISSUER , legacyAudienceSet );
374+ String fullAltIssuer = addNonConflictingSecurityDefinition (
375+ swagger , ApiIssuerConfigs .GOOGLE_ID_TOKEN_ISSUER_ALT , legacyAudienceSet );
376+ operation .addSecurity (fullIssuer , ImmutableList .<String >of ());
377+ operation .addSecurity (fullAltIssuer , ImmutableList .<String >of ());
396378 }
397379 }
398380
@@ -484,16 +466,14 @@ private static List<String> getEnumValues(TypeToken<?> t) {
484466 return values ;
485467 }
486468
487- private static ImmutableMap <String , List <String >> createAudiences (Iterable <String > audiences ) {
488- return ImmutableMap .<String , List <String >>of ("audiences" , ImmutableList .copyOf (audiences ));
489- }
490-
491- private static SecuritySchemeDefinition toScheme (IssuerConfig issuerConfig ) {
469+ private static SecuritySchemeDefinition toScheme (
470+ IssuerConfig issuerConfig , ImmutableSet <String > audiences ) {
492471 OAuth2Definition tokenDef = new OAuth2Definition ().implicit ("" );
493472 tokenDef .setVendorExtension ("x-google-issuer" , issuerConfig .getIssuer ());
494473 if (!com .google .common .base .Strings .isNullOrEmpty (issuerConfig .getJwksUri ())) {
495474 tokenDef .setVendorExtension ("x-google-jwks_uri" , issuerConfig .getJwksUri ());
496475 }
476+ tokenDef .setVendorExtension ("x-google-audiences" , COMMA_JOINER .join (audiences ));
497477 return tokenDef ;
498478 }
499479
@@ -507,17 +487,20 @@ private static Map<String, SecuritySchemeDefinition> getOrCreateSecurityDefiniti
507487 return securityDefinitions ;
508488 }
509489
510- private static void addNonConflictingSecurityDefinition (
511- Swagger swagger , IssuerConfig issuerConfig ) throws ApiConfigException {
490+ private static String addNonConflictingSecurityDefinition (
491+ Swagger swagger , IssuerConfig issuerConfig , ImmutableSet <String > audiences )
492+ throws ApiConfigException {
512493 Map <String , SecuritySchemeDefinition > securityDefinitions =
513494 getOrCreateSecurityDefinitionMap (swagger );
495+ String issuerPlusHash = String .format ("%s-%x" , issuerConfig .getName (), audiences .hashCode ());
514496 SecuritySchemeDefinition existingDef = securityDefinitions .get (issuerConfig .getName ());
515- SecuritySchemeDefinition newDef = toScheme (issuerConfig );
497+ SecuritySchemeDefinition newDef = toScheme (issuerConfig , audiences );
516498 if (existingDef != null && !existingDef .equals (newDef )) {
517499 throw new ApiConfigException (
518500 "Multiple conflicting definitions found for issuer " + issuerConfig .getName ());
519501 }
520- swagger .securityDefinition (issuerConfig .getName (), newDef );
502+ swagger .securityDefinition (issuerPlusHash , newDef );
503+ return issuerPlusHash ;
521504 }
522505
523506 public static class SwaggerContext {
0 commit comments