Comment puis-je Protéger mon API qui a été créée en utilisant Google Cloud Endpoints?
L'API est un backend vers une application mobile. Je n'ai pas besoin d'authentification de l'utilisateur. J'ai simplement besoin d'un moyen de sécuriser l'accès à cette API. Actuellement, mon backend est exposée.
le documentation semble ne parler que d'authentification et d'autorisation de l'utilisateur, ce qui n'est pas ce dont j'ai besoin ici. J'ai juste besoin de s'assurer que mon application mobile peut parler à ce serveur et personne d'autre.
3 réponses
Oui, vous pouvez le faire: utiliser l'authentification pour sécuriser vos points d'accès sans authentification de l'utilisateur.
j'ai découvert que cette façon de faire n'est pas bien documentée, et je ne l'ai pas vraiment fait moi-même, mais j'ai l'intention de faire attention quand je l'ai vu être discuté sur certaines des vidéos de IO13 (je pense que c'est là que je l'ai vu):
voici ma compréhension de ce qui est impliqué:
- créer un Google Projet API (bien que cela n'implique pas vraiment leur API, autre que l'authentification elle-même).
- créer des ID client de serment qui sont liés à votre application via son nom de paquet et L'empreinte SHA1 du certificat avec lequel vous signerez l'application.
vous ajouterez ces codes d'identification de client à la liste des codes d'identification acceptables pour vos paramètres. Vous ajouterez le paramètre User à vos endpoints, mais il sera null puisqu'aucun utilisateur n'est spécifié.
@ApiMethod(
name = "sendInfo",
clientIds = { Config.WEB_CLIENT_ID, Config.MY_APP_CLIENT_ID, Config.MY_DEBUG_CLIENT_ID },
audiences = { Config.WEB_CLIENT_ID }
// Yes, you specify a 'web' ID even if this isn't a Web client.
)
public void sendInfo(User user, Info greeting) {
il y a de la documentation décente à propos de ce qui précède, ici: https://developers.google.com/appengine/docs/java/endpoints/auth
votre application client spécifiera ces identifiants lors de la formulation de l'appel de service. Tous les détails de serment seront pris en charge dans les coulisses sur votre appareil client de sorte que vos ID de client sont traduits en jetons d'authentification.
HttpTransport transport = AndroidHttp.newCompatibleTransport();
JsonFactory jsonFactory = new JacksonFactory();
GoogleAccountCredential credential = GoogleAccountCredential.usingAudience( ctx, Config.WEB_CLIENT_ID );
//credential.setSelectedAccountName( user ); // not specify a user
Myendpoint.Builder builder = new Myendpoint.Builder( transport, jsonFactory, credential );
ce code client est ma meilleure supposition - désolé. Si quelqu'un d'autre a une référence pour exactement ce que le code client devrait ressembler, alors je serais aussi intéressé.
Je suis désolé de dire que Google ne fournit pas une solution pour votre problème (qui est mon problème aussi). Vous pouvez utiliser leur mécanisme de clé API (voir ) https://developers.google.com/console/help/new/#usingkeys ), mais il y a un énorme trou dans cette stratégie grâce à L'API explorer de Google (voir https://developers.google.com/apis-explorer/#p / ), qui est un excellent outil de développement pour tester les API, mais qui expose toutes les API de point final Cloud, pas seulement API services de Google. Cela signifie que n'importe qui avec le nom de votre projet peut parcourir et appeler votre API à leur guise puisque L'Explorateur D'API contourne la sécurité de la clé D'API. J'ai trouvé une solution (basée sur la grande réponse de bossylobster à ce post: API D'accès Simple (clé de développeur) avec Google Cloud Endpoint (Python) ), qui consiste à passer un champ de requête qui ne fait pas partie de la définition de requête de message dans votre API client, puis de le lire dans votre serveur API. Si vous ne trouvez pas le champ sans-papiers, vous soulevez une exception non autorisée. Cela va boucher le trou créé par L'Explorateur API. Dans iOS (que j'utilise pour mon application), vous ajoutez une propriété à chaque classe de requêtes (celles créées par l'outil générateur D'API de Google) comme suit:
@property (copy) NSString *hiddenProperty;
et définissez sa valeur à une clé que vous choisissez. Dans votre code serveur (python dans mon cas) vous vérifier son existence et barf si vous ne voyez pas ou n'est pas définie à la valeur de votre serveur et le client sera d'accord sur:
mykey,keytype = request.get_unrecognized_field_info('hiddenProperty')
if mykey != 'my_supersecret_key':
raise endpoints.UnauthorizedException('No, you dont!')
Espère que cela vous met sur la bonne voie
la documentation est réservée au client. J'ai besoin de la documentation sur la façon de fournir la fonctionnalité de compte de Service du côté du serveur.
cela peut vouloir dire plusieurs choses, mais j'aimerais aborder ce que je pense que la question se pose. Si vous ne voulez que votre compte de service pour accéder à votre service, alors vous pouvez juste ajouter le clientId du compte de service à vos annotations @Api/@ApiMethod, construire un GoogleCredential, et d'appeler votre service comme vous le feriez normalement. Spécifiquement...
dans la console du développeur google, créez un nouveau compte de service. Cela va créer un .fichier p12 qui est automatiquement téléchargé. C'est utilisé par le client dans la documentation à laquelle vous renvoyez. Si vous ne pouvez pas garder le .p12 sécurisé, ce n'est pas beaucoup plus sécurisé que d'un mot de passe. je suppose que c'est la raison pour laquelle cela n'est pas explicitement indiqué dans la documentation des paramètres du nuage.
vous ajoutez l'ID du CLIENT affiché dans la console du développeur google aux clientIds de votre annotation @Api ou @ApiMethod
import com.google.appengine.api.users.User
@ApiMethod(name = "doIt", scopes = { Constants.EMAIL_SCOPE },
clientIds = { "12345678901-12acg1ez8lf51spfl06lznd1dsasdfj.apps.googleusercontent.com" })
public void doIt(User user){ //by convention, add User parameter to existing params
// if no client id is passed or the oauth2 token doesn't
// match your clientId then user will be null and the dev server
// will print a warning message like this:
// WARNING: getCurrentUser: clientId 1234654321.apps.googleusercontent.com not allowed
//..
}
vous construisez un client de la même manière que vous le feriez avec la version non sécurisée, la seule différence étant que vous créez un objet GoogleCredential à passer au MyService de votre service.Constructeur.
HttpTransport httpTransport = new NetHttpTransport(); // or build AndroidHttpClient on Android however you wish
JsonFactory jsonFactory = new JacksonFactory();
// assuming you put the .p12 for your service acccount
// (from the developer's console) on the classpath;
// when you deploy you'll have to figure out where you are really
// going to put this and load it in the appropriate manner
URL url = getClass().class.getResource("/YOURAPP-b12345677654.p12");
File p12file = new File(url.toURI());
GoogleCredential.Builder credentialBuilder = new GoogleCredential.Builder();
credentialBuilder.setTransport(httpTransport);
credentialBuilder.setJsonFactory(jsonFactory);
//NOTE: use service account EMAIL (not client id)
credentialBuilder.setServiceAccountId("12345678901-12acg1ez8lf51spfl06lznd1dsasdfj@developer.gserviceaccount.com"); credentialBuilder.setServiceAccountScopes(Collections.singleton("https://www.googleapis.com/auth/userinfo.email"));
credentialBuilder.setServiceAccountPrivateKeyFromP12File(p12file);
GoogleCredential credential = credentialBuilder.build();
invoquez maintenant votre client généré de la même manière vous voulez la version non sécurisée, sauf le constructeur prend notre Google credential d'en haut comme le dernier argument
MyService.Builder builder = new MyService.Builder(httpTransport, jsonFactory, credential);
builder.setApplicationName("APP NAME");
builder.setRootUrl("http://localhost:8080/_ah/api");
final MyService service = builder.build();
// invoke service same as unsecured version