oauth2

oauth2.

Einleitung

Diese Seite entstand - nach Umstieg auf ein Android Smartphone - als ich nichts zur Todolistenverwaltung gefunden habe. Zumindest keine Lösung mit nativen Anwendungen

  • am Windows Desktop (Arbeit)

  • am Ubuntu Laptop (auf der Couch)

  • und auf den Telefon (Android)

Mein angedachter Workaround:

  • eine bestehende Android App verwenden (gTasks), die Google Tasks als Cloud Speicher nutzt.

  • Dazu dann eine rudimentäre Java SWT Anwendung für PC und Laptop erstellen.

der Widerstand

Google bietet eine Java API für den Zugriff auf die Tasks an (derzeit in BETA, Stand Januar 2013). Ein Downloadlink findet sich am Ende der Seite.

Der meiste Code/Forschungsaufwand geht eigentlich für die OAUTH2 Authentifizierung (Anmeldung) drauf.

OAUTH2 und Google Tasks

Ab hier wird der Weg zu einer funktionierenden Tasks Abfrage mit Java skizziert.

Der gezeigte Code ist aus meinen Unit Tests entnommen. Er erhält damit keinen Schönheitspreis, ist aber (derzeit) lauffähig.

die eigene Anwendung bei Google registrieren

Dieser Step ist nur einmalig für eine Anwendung zu durchlaufen.

Man registiert seine neue Anwendung, und schaltet für sie die Tasks API zur Nutzung frei. Von Google gibts dann ClientID und Client Secret für genau diese Anwendung. Das alles macht man bequem im Browser bei Google.

01.createProject

  • die Anwendung soll Zugriff auf die Tasks API bekommen

01.tasksAPI

  • Der Anwendung das Login mit OAUTH2 ermöglichen

    • API Access

    • Create an OAuth 2.0 client ID

01.createOAUTH2Id

  • Ich baue hier einen "Fat Client", d aher also "Installed Application" wählen

01.createClientId

01.GeneratedIds

Note
merken der ClientID, braucht man später im Code: *.apps.googleusercontent.com
Note
ebenfalls das Client Secrect merken: u0*lb6

AuthorizationCodeFlow der Google API ansprechen

Jetzt geht es in den Java Code. Beim Login dreht sich alles um die AuthorizationCodeFlow Klasse. Die wird hier erst einmal initialisiert.

  • fuer die Anwendung (ClientID / Client Secret)

  • für Task Zugriffe auf den Google User Account "userGoogleAccount"

  • Userdaten werden in der Datei "MyAppsDemoCredentialStore.json" aufbewahrt

	HttpTransport httpTransport = new NetHttpTransport();
	JsonFactory   jsonFactory = new GsonFactory();

	String		  GOOGLE_OAUTH2_TOKEN_URI	= "https://accounts.google.com/o/oauth2/token";	// google server für oauth2 tokens
	String		  GOOGLE_OAUTH2_AUTH_URI	= "https://accounts.google.com/o/oauth2/auth";	// google server für oauth2

	// Ablage der Zugänge Appuser im Dateisystem..
	FileCredentialStore credentialStore = new FileCredentialStore(new File("MyAppsDemoCredentialStore.json"), jsonFactory);

	// Initialisieren OAuth2 flow
	AuthorizationCodeFlow authorizationCodeFlow = new AuthorizationCodeFlow.Builder(BearerToken.authorizationHeaderAccessMethod(), httpTransport,
			jsonFactory, new GenericUrl(GOOGLE_OAUTH2_TOKEN_URI),
				new ClientParametersAuthentication(
					"****.apps.googleusercontent.com", 			// CLIENT Id     (bleibt konstant für diese Anwendung)
					"u0*************b6"),						// CLIENT Secret (bleibt konstant für diese Anwendung)
			"****.apps.googleusercontent.com", GOOGLE_OAUTH2_AUTH_URI)
			.setCredentialStore(credentialStore)
			.setScopes(Arrays.asList("https://www.googleapis.com/auth/tasks"))	// anzufordernde Rechte (Hier: Zugriff auf google tasks)
			.build();

	assertNotNull(authorizationCodeFlow);

	// Zugangscredentials bereits in credentialStore abgelegt (Folgeaufruf ?)
	Credential storedUserCredential =  authorizationCodeFlow.loadCredential(userGoogleAccount);
	assertNull(storedUserCredential); // das soll hier der erste Aufruf sein.

Damit hat man mal die Verbindung vorbereitet, Die Datei mit den User Credentials ist leer angelegt.

2.MyAppsDemoCredentialStoreEmpty

Anwendung den Zugriff auf Tasks eines Users erlauben

Dieser Codeteil muss für jeden neuen User durchlaufen werden.

Zugriff erteilt der jeweilige User im Browser. Seine Credentials werden lokal abgespeichert für spätere Verwendung durch die Anwendung.

	// URL erstellen, damit kann der User dann gleich im Browser den Zugriff dieser Anwendung
	// auf die Tasks in seinem google Account erlauben..
	AuthorizationCodeRequestUrl authorizationUrl = getAuthorizationCodeFlow().newAuthorizationUrl();
	authorizationUrl.setRedirectUri("urn:ietf:wg:oauth:2.0:oob");
	String authorizationUrlString = authorizationUrl.build();

	// URL im Web Browser öffnen ...
	System.out.println("Attempting to open a web browser to start the OAuth2 flow");
	openBrowser(URI.create(authorizationUrlString));

	// nun muss der User den angezeigten Code übernehmen in die App:
	System.out.print("Den angezeigten Code bitte hier kopieren: ");
	String code = new Scanner(System.in).nextLine();

	// und jetzt wird die Zugriffserlaubnis für diesen User auf der Festplatte permanent abgespeichert
	TokenResponse response = authorizationCodeFlow.newTokenRequest(code).setRedirectUri("urn:ietf:wg:oauth:2.0:oob").execute();
	authorizationCodeFlow.createAndStoreCredential(response, userGoogleAccount);

Im Browser gibt der User die Zugriff auf seine Tasks frei

2b.AntragZugriff

Dafür gibt es einen Bestätigungscode von Google, den kopiert der User aus dem Browser.

2b.AntragAkzeptiert

Den Code muss der Anwendung wieder mitgeteilt werden

2b.CodeUebertragen

Diese generiert damit ein Token und speichert es lokal (hier im json Format) im Dateisystem ab.

2b.CodeGespeichert

Login bei Google

Bei jedem Anwendungsstart muss der jeweilige User bei Google angemeldet werden, die Credentials dazu wurden im Step zuvor lokal gespeichert.

	Credential storedUserCredential =  authorizationCodeFlow.loadCredential(userGoogleAccount);	// use XXXXX@gmail.com Account
	assertNotNull(storedUserCredential);

	HttpTransport httpTransport = new NetHttpTransport();
	JsonFactory   jsonFactory = new GsonFactory();
	Tasks tasksService = new Tasks(httpTransport, jsonFactory, storedUserCredential);
	assertNotNull(tasksService);

Abfrage Tasks

So bei Google angemeldet kann man von dort die Tasks zum User Account auslesen.

Dazu nutzt man die Google API Java Library als Wrapper über die eigentlichen REST Aufrufe gegen die Google Server.

	// Tasklisten abfragen ..
	TaskLists returnedLists = tasksService.tasklists().list().execute();

	for(TaskList list : returnedLists.getItems() )
	{
		System.out.println("* " + list.getId() + "/" + list.getTitle() + "/" + list.getEtag());

		// Tasks in aktueller Taskliste abfragen..

		com.google.api.services.tasks.Tasks.TasksOperations.List execTasks = tasksService.tasks().list(list.getId());
		execTasks.setShowCompleted(false);
		execTasks.setShowDeleted(false);

		com.google.api.services.tasks.model.Tasks tasks = execTasks.execute();
		if( tasks != null && ! tasks.isEmpty() && tasks.getItems() != null)
		{
			for(Task t : tasks.getItems())
			{
				System.out.println("       - " + t.getId() + "/" + t.getTitle() + "/" + t.getStatus() + "/"
				+ t.getDue() + "/ [" + t.getNotes() + "]");
			}
		}
	}

Am Ziel, der Code gibt die aktuellen Tasklisten inclusive deren Einträge aus:

4.tasksoutput

Referenzen