I've deployed the following endpoints framework API to my Google appengine application + generated and deployed the OpenAPI configuration for Google's "Client-API service" + generated the endpoints client API for my Android app successfully:
@Api(
name = "endpoint",
version = "v1",
apiKeyRequired = AnnotationBoolean.TRUE,
authenticators = {EspAuthenticator.class},
issuers = {
@ApiIssuer(
name = "firebase",
issuer = "https://securetoken.google.com/MY_PROJECT_ID",
jwksUri = "https://www.googleapis.com/service_accounts/v1/metadata/x509/securetoken@system.gserviceaccount.com")
},
issuerAudiences = {
@ApiIssuerAudience(name = "firebase", audiences = "MY_PROJECT_ID")
},
namespace =
@ApiNamespace(
ownerDomain = "xxxxx",
ownerName = "xxxxx"
)
public class API {
@ApiMethod(name = "procesOrderRequest", path = "customer/orders/request")
public Order processCutomerOrderRequest(User user, OrderRequest orderRequest) throws UnauthorizedException {
log.info("procesOrderRequest(): CustomerId: " + orderRequest.getCustomer());
log.info("procesOrderRequest(): bagId: " + orderRequest.getBagId());
log.info("processCutomerOrderRequest(): customerId: " + orderRequest.getCustomer());
if (user == null) {
throw new UnauthenticatedException("Unauthorized user by RR");
}
Order order = new Order();
order.setBagId(orderRequest.getBagId());
order.setPriority(orderRequest.getPriority());
order.setOrderId(orderRequest.getBagId() + 1000);
return order;
}
}
As you can see from above I'm using firebase authentication and API keys.
In my Android application I successfully login my Firebase user, but if I try to execute the following an endpoint client API request
private class ContactBackendTask extends AsyncTask<Void, Void, Void> {
String mIDToken = null;
@Override
protected Void doInBackground(Void... voids) {
FirebaseUser user = mFirebaseAuthenticator.getCurrentUser();
user.getIdToken(true).addOnSuccessListener(new OnSuccessListener<GetTokenResult>() {
@Override
public void onSuccess(GetTokenResult result) {
mIDToken = result.getToken();
//Do whatever
Log.d("attempLogin", "GetTokenResult result = " + mIDToken);
}
});
Endpoint.Builder endpoint = new Endpoint.Builder(AndroidHttp.newCompatibleTransport(), new AndroidJsonFactory(), null);
endpoint.setRootUrl("https://MY_PROJECT_ID.appspot.com/_ah/api/");
endpoint.setApplicationName("MY_PROJECT_ID");
Endpoint service = endpoint.build();
OrderRequest orderRequest = new OrderRequest();
orderRequest.setBagId(35);
orderRequest.setPriority(9);
orderRequest.setCustomer("someUser@gmail.com");
try {
Endpoint.ProcesOrderRequest request = service.procesOrderRequest(orderRequest);
Order order = request.setKey("MY_API_KEY").setOauthToken(mIDToken).execute();
Log.d("attempLogin", "OrderId result = " + order.getOrderId());
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
return null
}
I get the following response from Google's Endpoints Management service:
400 Bad Request
{
"code": 400,
"errors": [
{
"domain": "global",
"message": "java.lang.IllegalArgumentException: No auth providers are defined in the config.",
"reason": "badRequest"
}
],
"message": "java.lang.IllegalArgumentException: No auth providers are defined in the config."
}
Any idea, what I'm missing here?
I've followed the following Firebase specific authentication tutorial as well as the following Google Endpoints User Authentication tutorial.
Any idea or hint is very appreciated.
Update:
Here is the SERVICE_CONFIG_FILE used to deploy the endpoints API to Google's Service Management.
SecurityDefinitions from openenapi.json:
securityDefinitions":{
"api_key":{
"in":"query",
"name":"key",
"type":"apiKey"
},
"firebase":{
"authorizationUrl":"",
"flow":"implicit",
"type":"oauth2",
"x-google-issuer":"https://securetoken.google.com/my_project_id",
"x-google-jwks_uri":"https://www.googleapis.com/service_accounts/v1/metadata/x509/securetoken@system.gserviceaccount.com"
}
},
"swagger":"2.0"
Update 2:
Stacktrace from the App Engine console:
java.lang.IllegalArgumentException: No auth providers are defined in the config.
at com.google.api.auth.Authenticator.create (Authenticator.java:178)
at com.google.api.auth.Authenticator.create (Authenticator.java:171)
at com.google.api.server.spi.auth.EspAuthenticator.<init> (EspAuthenticator.java:54)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0 (Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance (NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance (DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance (Constructor.java:423)
at java.lang.Class.newInstance (Class.java:443)
at com.google.api.server.spi.request.Auth$1.apply (Auth.java:57)
at com.google.api.server.spi.request.Auth$1.apply (Auth.java:51)
Update 3:
<env-variables>
<env-var name="ENDPOINTS_SERVICE_NAME" value="my_project_id.appspot.com" />
<env-var name="ENDPOINTS_SERVICE_VERSION" value="2018-03-29r0" />
</env-variables>
Of course,
"my_project_id"
is just an example ID for this post. I don't want to post my real project id here.
And
"2018-03-29r0"
is the the ID which is generated after deploying the openapi.json file with the command
gcloud endpoints services deploy target/openapi-docs/openapi.json
Update 4:
However I get now the following response from my appengine backend application
503 Service Unavailable
{
"code": 503,
"errors": [
{
"domain": "global",
"message": "com.google.api.auth.UnauthenticatedException: Unauthorized user by RR",
"reason": "backendError"
}
],
"message": "com.google.api.auth.UnauthenticatedException: Unauthorized user by RR"
}
when executing in my Android app
Order order = request.setKey("MY_API_KEY").setOauthToken(mIDToken).execute();
The exception UnauthenticatedException is triggered due to fact, that the backend API method processCutomerOrderRequest() validates user == null although the firebase authentication of the user was signalled as "successfully logged in".
My question: What is wrong here? Maybe I shouldn't use the method setOauthToken() in my client app? Is the call correct?