"scope not allowed" on localhost only - google-app-engine

I'm getting started with Google App Engine with Java, and using Google Cloud Endpoints with OAuth 2.0. I have one simple endpoint working correctly, but only when deployed. When I run it on my local machine I get this error:
Mar 10, 2014 4:38:54 PM com.google.api.server.spi.WebApisUserService getCurrentUser
INFO: getCurrentUser: AccessToken; scope not allowed
Here is my endpoint code:
#Api(
name = "sd",
version = "v1",
scopes = { Constants.EMAIL_SCOPE },
clientIds = { Constants.WEB_CLIENT_ID, Constants.API_EXPLORER_CLIENT_ID })
public class Feeds {
public Feed sample(User user) {
if (user == null) {
return new Feed("Public Feed.");
} else {
return new Feed("Feed for " + user.getEmail());
}
}
}
...
public class Constants {
public static final String WEB_CLIENT_ID = "<snip>.apps.googleusercontent.com";
public static final String EMAIL_SCOPE = "https://www.googleapis.com/auth/userinfo.email";
public static final String API_EXPLORER_CLIENT_ID = com.google.api.server.spi.Constant.API_EXPLORER_CLIENT_ID;
}
As I said, when I deploy this and access it via the API Explorer in all works perfectly. When I have the OAuth toggle on, it returns Feed for <my email address>, and when I turn it off it returns Public Feed.
However, when run against my local machine it always returns Public Feed. When the OAuth toggle is on, it prints the error pasted at the top of this post to the server's console. I am accessing the two api explorers with the urls https://<app_id>.appspot.com/_ah/api/explorer and http://localhost:8888/_ah/api/explorer.
Can anyone help?

Related

Creates a default database in Firestore using Google.Apis.Appengine.v1 in C# library

I wanted to create cloud firestore database programmatically using c#, but I am getting error when I run the code. How would I fix permission related issue I am facing? Below is the code and error
private static AppengineService _appEngineService;
public static void IntializeAppEngine() {
GoogleCredential credential = GoogleCredential.GetApplicationDefault();
if (CloudManager.Credential.IsCreateScopedRequired)
{
credential = CloudManager.Credential.CreateScoped(
AppengineService.Scope.CloudPlatform);
}
_appEngineService = new AppengineService(
new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = CloudManager.ApplicationName
});
}
public static void AddCloudFirestore() {
IntializeAppEngine();
var body = new Application {
LocationId = "us-east1",
Id = "projects/" + CloudManager.ProjectId
};
var res = _appEngineService.Apps.Create(body).Execute();
}
Error:
Unhandled exception. The service appengine has thrown an exception.
HttpStatusCode is Forbidden.
Google.Apis.Requests.RequestError
The caller does not have permission [403]
Errors [
Message[The caller does not have permission] Location[ - ] Reason[forbidden] Domain[global]
]
Google.GoogleApiException: The service appengine has thrown an exception. HttpStatusCode is Forbidden. The caller does not have permission
at Google.Apis.Requests.ClientServiceRequest`1.ParseResponse(HttpResponseMessage response)
at Google.Apis.Requests.ClientServiceRequest`1.Execute()
at CloudResourceManager.FirebaseManagement.AddCloudFirestore()
Instead of Appengine, Cloud Firestore REST API can be used as Sarah suggested.
In c# Google.Apis.Firestore.v1 can be used to create cloud firestore.

Unable to get IAM security credentials from EC2 Instance Metadata Service error when using Aws Sdk in UWP

I'm working with Aws Sdk and I'm trying to implement a login UI using UWP. I followed this online tutorial (which is for WPF) and I tried to make it works for the Universal Windows Platform as well.
The core part of the source code is the following (please note that is 90% similar to the one posted in the tutorial. The "only difference" is that I used
InitiateAuthAsync
instead of
AdminInitiateAuthAsync
<!-- language: lang-cs -->
private readonly AmazonCognitoIdentityProviderClient _client;
private readonly string _clientId = "32fsoifj93fjsiispat";
public MainPage()
{
this.InitializeComponent();
var amazonCognitoIdentityProviderConfig = new AmazonCognitoIdentityProviderConfig();
amazonCognitoIdentityProviderConfig.ServiceURL = "https://cognito-idp.eu-central-1.amazonaws.com/";
_client = new AmazonCognitoIdentityProviderClient(amazonCognitoIdentityProviderConfig);
}
private async Task<bool> CheckPasswordAsync(string userName, string password)
{
try
{
List<HttpHeader> httpHeaders = new List<HttpHeader>();
HttpHeader httpHeader = new HttpHeader
{
HeaderName = "X-Amz-Target",
HeaderValue = "AWSCognitoIdentityProviderService.InitiateAuth"
};
httpHeaders.Add(httpHeader);
httpHeader = new HttpHeader
{
HeaderName = "Content-Type",
HeaderValue = "application/x-amz-json-1.1"
};
httpHeaders.Add(httpHeader);
var authReq = new InitiateAuthRequest()
{
ClientId = _clientId,
AuthFlow = AuthFlowType.USER_PASSWORD_AUTH,
};
authReq.AuthParameters.Add("USERNAME", userName);
authReq.AuthParameters.Add("PASSWORD", password);
var authResp = await _client.InitiateAuthAsync(authReq);
return true;
}
catch (Exception ex)
{
return false;
}
}
Please consider that it is working properly with WPF framework. I'm able to get the TokenId and RefreshToken.
But if I try to copy and paste the same code in UWP I get the exception:
'Unable to get IAM security credentials from EC2 Instance Metadata Service.'
And if I try to investigate with Fiddler I get the following error:
[Fiddler] The connection to '169.254.169.254' failed. Error: NetworkUnreachable (0x2743). System.Net.Sockets.SocketException A socket operation was attempted to an unreachable network 169.254.169.254:80
I really can't understand why it tries to connect to the '169.254.169.254' address. Googling around I found other people experiencing the same issue (for example here). Do you have any idea?

Managing user authentication in a GAE application

What is the best way to manage a user session in a Google App Engine application? Ideally I'd like to keep my application stateless and not save any user related data in memory, however I'm also afraid to send user credentials of the network on every request (not to mention authenticating the user on every request would require a call to the Datastore which costs money).
I checked out google's OAuth 2.0 solution but from my understanding it helps if my application wants to connect to any of the google APIs and needs permission from the client to access his google account.
Is there a go to way for managing user session? The most common scenario is to know which user initiated this request without having to send the userId as a request parameter.
Please note that we are not using third party providers. The user registers himself to our page normally and has a custom account. I'm not looking for tools that help integrate authentication with third party services. Otherwise I'd be using google's OAuth 2.0 or similar API
You can Always implement Authenticator Interface.
public class MyAuthenticator implements Authenticator {
#Override
public User authenticate(HttpServletRequest request) {
HttpSession session = request.getSession(false);
//
return null;// if not authenticated, otherwise return User object.
}
}
// Endpoints class.
#Api(name = "example", authenticators = { MyAuthenticator.class })
public class MyEndpoints {
public Profile getProfile(User user) {
if (user == null) {
throw new UnauthorizedException("Authorization required");
}
return new Profile(user.getEmail(), "displayName");
}
// store this class somewhere in models
public class Profile {
private String email;
private String displayName;
public Profile(String email, String displayName) {
this.email = email;
this.displayName = displayName;
}
public String getEmail() {
return email;
}
public String getdisplayName() {
return displayName;
}
}
}
Use the HttpServletRequest object to implement classic session based login or use your own custom header. Well that depends on your case. Return null when not authenticated and return User object when authenticated. Also implement some kind of encryption on both sides(client and server), so as to stop someone having the session key to access your api.

(Android Studio) Connecting an app to Google Endpoints Module

I'm having trouble following the second step here.
I really don't understand how this sample does anything other than return a simple toast message. How does it utilize the API to display that message?
class EndpointsAsyncTask extends AsyncTask<Pair<Context, String>, Void, String> {
private static MyApi myApiService = null;
private Context context;
#Override
protected String doInBackground(Pair<Context, String>... params) {
if(myApiService == null) { // Only do this once
MyApi.Builder builder = new MyApi.Builder(AndroidHttp.newCompatibleTransport(),
new AndroidJsonFactory(), null)
// options for running against local devappserver
// - 10.0.2.2 is localhost's IP address in Android emulator
// - turn off compression when running against local devappserver
.setRootUrl("http://10.0.2.2:8080/_ah/api/")
.setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() {
#Override
public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest) throws IOException {
abstractGoogleClientRequest.setDisableGZipContent(true);
}
});
// end options for devappserver
myApiService = builder.build();
}
context = params[0].first;
String name = params[0].second;
try {
return myApiService.sayHi(name).execute().getData();
} catch (IOException e) {
return e.getMessage();
}
}
#Override
protected void onPostExecute(String result) {
Toast.makeText(context, result, Toast.LENGTH_LONG).show();
}
I'm afraid my this sample is too complex for my limited knowledge. How exactly do I "talk" to the Google Endpoints Module when running an app? Specifically, What is EndpointsAsyncTask();?
Are there any resources listing all the methods available to me? Is there a simpler example of an app communicating with a Google Cloud Endpoint?
The service methods available to you are defined by the backend source in section 1.
In the example you posted, this line: myApiService.sayHi(name).execute()
is an actual invocation call to the backend that you defined by annotating #ApiMethod("sayHi") on the method in the MyEndpoint.java class of your backend module.
The reason your Android app defines an EndpointsAsyncTask is because slow operations such as calls that hit the network need to happen off of the UI thread to avoid locking the UI. The demo simply puts the returned value into a Toast but you could modify onPostExecute() to do whatever you'd like with the result.
For more info on Google Endpoints check out:
https://cloud.google.com/appengine/docs/java/endpoints/
And for info about using an Android AsyncTask look here:
http://developer.android.com/reference/android/os/AsyncTask.html

Enforcing Basic Authentication with RestEasy & TJWS

We use Resteasy to communicate between multiple backend servers & we want to lock this down so not just anyone can attach a client or browser to the restlet server.
We're using Resteasy 3.04 and as our backend services are numerous but very light-weight an embeddded TJWS webserver.
Example Server code:
public class RestEasySSLBasicAuthenticationServer {
static TJWSEmbeddedJaxrsServer webServer;
static class BasicAthenticationSecurityDomain implements SecurityDomain {
#Override
public Principal authenticate(String aUsername, String aPassword) throws SecurityException {
System.out.println("User:" + aUsername + " Password" + aPassword);
if (aPassword.equals("password") == false) {
throw new SecurityException("Access denied to user " + aUsername);
}
return null;
}
#Override
public boolean isUserInRoll(Principal aUsername, String aRole) {
// No role based checks so return true
return true;
}
}
public static void main(String[] args) throws Exception {
// Create embedded TJWS web server
webServer = new TJWSEmbeddedJaxrsServer();
// Set up SSL connections on server
webServer.setSSLPort(8081);
webServer.setSSLKeyStoreFile("K:\\source\\RestEasyTest\\server_localhost.jks");
webServer.setSSLKeyStorePass("krypton");
webServer.setSSLKeyStoreType("JKS");
// Add basic HTTP authentication to the server
webServer.setSecurityDomain( new BasicAthenticationSecurityDomain() );
// Add the restlet resource
webServer.getDeployment().getActualResourceClasses().add(PlayerResource.class);
// Start the web server
webServer.start();
// Run until user presses a key
System.out.print("Web server started. Press a key to stop...");
System.in.read();
// Stop the web server
webServer.stop();
}
}
Example client code:
public class RestEasySSLBasicAuthenticationClient {
public static void main(String[] args) throws Exception {
// Set up the keystore
System.setProperty("javax.net.ssl.keyStore", "K:\\source\\RestEasyTest\\client_localhost.jks");
System.setProperty("javax.net.ssl.keyStoreType", "JKS");
System.setProperty("javax.net.ssl.keyStorePassword", "krypton");
// Create a new Restlet client
Client restletClient = ClientBuilder.newClient();
// *** Even WITHOUT these credentitials we can access the restlet
// restletClient.register(new BasicAuthentication("username", "password"));
// Set up the restlet request target.
WebTarget request = restletClient.target("https://localhost:8081/player/{id}");
request = request.resolveTemplate("id", Long.valueOf(1));
// Build the restlet request
Invocation invocation = request.request("application/xml").buildGet();
// Call the restlet and get returned object
Player result = invocation.invoke( Player.class );
System.out.println(result.toString());
}
}
Using the test client and a registered authentication filter works and as expected I can a 401 access error if I get the password incorrect.
However if no authentication is registered at the client then the server never calls the SecurityDomain check and access is allowed.
How do I enforce a login at the server?
You can ensure all users are authenticated by enabling security on the embedded TJWS web server.
webServer.getDeployment().setSecurityEnabled(true);

Resources