Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

import java.util.Base64;

import org.springframework.grpc.server.security.GrpcSecurity;
import org.springframework.grpc.internal.GrpcHeaders;

import io.grpc.CallOptions;
import io.grpc.Channel;
Expand Down Expand Up @@ -50,7 +50,7 @@ public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT
CallOptions callOptions, Channel next) {
return new SimpleForwardingClientCall<>(next.newCall(method, callOptions)) {
public void start(ClientCall.Listener<RespT> responseListener, io.grpc.Metadata headers) {
headers.put(GrpcSecurity.AUTHORIZATION_KEY,
headers.put(GrpcHeaders.AUTHORIZATION_KEY,
"Basic " + Base64.getEncoder()
.encodeToString((BasicAuthenticationInterceptor.this.username + ":"
+ BasicAuthenticationInterceptor.this.password)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

import java.util.function.Supplier;

import org.springframework.grpc.server.security.GrpcSecurity;
import org.springframework.grpc.internal.GrpcHeaders;

import io.grpc.CallOptions;
import io.grpc.Channel;
Expand Down Expand Up @@ -49,7 +49,7 @@ public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(MethodDescriptor<ReqT
CallOptions callOptions, Channel next) {
return new SimpleForwardingClientCall<>(next.newCall(method, callOptions)) {
public void start(ClientCall.Listener<RespT> responseListener, io.grpc.Metadata headers) {
headers.put(GrpcSecurity.AUTHORIZATION_KEY,
headers.put(GrpcHeaders.AUTHORIZATION_KEY,
"Bearer " + BearerTokenAuthenticationInterceptor.this.token.get());
super.start(responseListener, headers);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright 2023-present the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.grpc.internal;

import io.grpc.Metadata;

/**
* Common gRPC headers.
* <p>
* NOTE: Even though this class visibility is `public` it is intended for internal use
* only and not recommended for direct use.
*
* @author Andrey Litvitski
*/
public final class GrpcHeaders {

private GrpcHeaders() {
}
Comment on lines +28 to +32
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If anyone has any good suggestions for what to call this class, that would be great. Honestly, I haven't come up with anything for the current one either.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about GrpcHeaders? It mirrors Spring's own HttpHeaders convention — a well-known precedent for a constants class holding header key names. Since gRPC's Metadata is the equivalent of HTTP headers, the analogy feels natural. It's short, discoverable, and leaves room to add other standard headers later without the name feeling off. GrpcMetadataKeys isn't bad, but "Keys" is slightly redundant since all the fields are keys by definition.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, it does look good - I was thinking the same thing myself. Thanks. I think it's definitely better than what we have now, though that’s debatable, but I still agree with you.


/**
* A constant key used for storing and retrieving the "Authorization" header from gRPC
* metadata. This key is used to handle authorization information in gRPC requests.
*
* <p>
* The key is defined with the name "Authorization" and uses the ASCII string
* marshaller for encoding and decoding the header value.
* </p>
*/
public static final Metadata.Key<String> AUTHORIZATION_KEY = Metadata.Key.of("Authorization",
Metadata.ASCII_STRING_MARSHALLER);

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import org.jspecify.annotations.Nullable;

import org.springframework.grpc.internal.GrpcHeaders;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.server.resource.authentication.BearerTokenAuthenticationToken;
Expand All @@ -41,7 +42,7 @@ public class BearerTokenAuthenticationExtractor implements GrpcAuthenticationExt

@Override
public @Nullable Authentication extract(Metadata headers, Attributes attributes, MethodDescriptor<?, ?> method) {
String auth = headers.get(GrpcSecurity.AUTHORIZATION_KEY);
String auth = headers.get(GrpcHeaders.AUTHORIZATION_KEY);
if (auth == null) {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,18 +61,6 @@
public final class GrpcSecurity
extends AbstractConfiguredSecurityBuilder<AuthenticationProcessInterceptor, GrpcSecurity> {

/**
* A constant key used for storing and retrieving the "Authorization" header from gRPC
* metadata. This key is used to handle authorization information in gRPC requests.
*
* <p>
* The key is defined with the name "Authorization" and uses the ASCII string
* marshaller for encoding and decoding the header value.
* </p>
*/
public static final Metadata.Key<String> AUTHORIZATION_KEY = Metadata.Key.of("Authorization",
Metadata.ASCII_STRING_MARSHALLER);

/**
* The order value for the context filter in the gRPC security framework. This
* constant defines the position of the context filter in the filter chain. A lower
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

import org.jspecify.annotations.Nullable;

import org.springframework.grpc.internal.GrpcHeaders;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;

Expand All @@ -42,7 +43,7 @@ public class HttpBasicAuthenticationExtractor implements GrpcAuthenticationExtra

@Override
public @Nullable Authentication extract(Metadata headers, Attributes attributes, MethodDescriptor<?, ?> method) {
String auth = headers.get(GrpcSecurity.AUTHORIZATION_KEY);
String auth = headers.get(GrpcHeaders.AUTHORIZATION_KEY);
if (auth == null) {
return null;
}
Expand Down
Loading