diff --git a/api/src/main/java/io/grpc/CallCredentials.java b/api/src/main/java/io/grpc/CallCredentials.java index eb92a6f15fa..f755078ff35 100644 --- a/api/src/main/java/io/grpc/CallCredentials.java +++ b/api/src/main/java/io/grpc/CallCredentials.java @@ -65,6 +65,24 @@ public abstract void applyRequestMetadata( public void thisUsesUnstableApi() { } + /** + * Determines whether the security level of the transport is higher than or equal to the minimum + * security level required to transfer these {@link CallCredentials}. + * + *

It is intended to be called from {@link #applyRequestMetadata} before sending any individual + * RPC. The credentials should not be sent if this method returns {@code false}. More details can + * be found in + * gRFC L62. + * + * @param requestInfo request-related information + * @param minSecurity minimum security level required by these {@code CallCredentials} + */ + protected static final boolean allowedSecurityLevel( + RequestInfo requestInfo, SecurityLevel minSecurity) { + return requestInfo.getSecurityLevel().compareTo(minSecurity) >= 0; + } + /** * The outlet of the produced headers. Not thread-safe. * diff --git a/auth/src/main/java/io/grpc/auth/GoogleAuthLibraryCallCredentials.java b/auth/src/main/java/io/grpc/auth/GoogleAuthLibraryCallCredentials.java index b4b7f5b89e4..64383f7b437 100644 --- a/auth/src/main/java/io/grpc/auth/GoogleAuthLibraryCallCredentials.java +++ b/auth/src/main/java/io/grpc/auth/GoogleAuthLibraryCallCredentials.java @@ -98,7 +98,7 @@ public GoogleAuthLibraryCallCredentials(Credentials creds) { public void applyRequestMetadata( RequestInfo info, Executor appExecutor, final MetadataApplier applier) { SecurityLevel security = info.getSecurityLevel(); - if (requirePrivacy && security != SecurityLevel.PRIVACY_AND_INTEGRITY) { + if (requirePrivacy && !allowedSecurityLevel(info, SecurityLevel.PRIVACY_AND_INTEGRITY)) { applier.fail(Status.UNAUTHENTICATED .withDescription("Credentials require channel with PRIVACY_AND_INTEGRITY security level. " + "Observed security level: " + security)); diff --git a/auth/src/test/java/io/grpc/auth/GoogleAuthLibraryCallCredentialsTest.java b/auth/src/test/java/io/grpc/auth/GoogleAuthLibraryCallCredentialsTest.java index 75026fd7c18..38023363fc2 100644 --- a/auth/src/test/java/io/grpc/auth/GoogleAuthLibraryCallCredentialsTest.java +++ b/auth/src/test/java/io/grpc/auth/GoogleAuthLibraryCallCredentialsTest.java @@ -329,6 +329,22 @@ public void googleCredential_integrityDenied() { assertEquals(Status.Code.UNAUTHENTICATED, status.getCode()); } + @Test + public void googleCredential_noneDenied() { + final AccessToken token = new AccessToken("allyourbase", new Date(Long.MAX_VALUE)); + final Credentials credentials = GoogleCredentials.create(token); + + GoogleAuthLibraryCallCredentials callCredentials = + new GoogleAuthLibraryCallCredentials(credentials); + callCredentials.applyRequestMetadata( + new RequestInfoImpl(SecurityLevel.NONE), executor, applier); + runPendingRunnables(); + + verify(applier).fail(statusCaptor.capture()); + Status status = statusCaptor.getValue(); + assertEquals(Status.Code.UNAUTHENTICATED, status.getCode()); + } + @Test public void serviceUri() throws Exception { GoogleAuthLibraryCallCredentials callCredentials =