SocialConnect - Facebook API-Verständnis

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • SocialConnect - Facebook API-Verständnis

    Hallo,

    so kurz vor Jahresende möchte ich mich noch mit SocialConnect, in diesem Fall ersteinmal mit FacebookConnect, beschäftigen. Ich habe mir nun die API und ein-zwei HowTo-Webseiten angesehen, habe aber immer noch nicht wirklich verstanden, wie das funktionieren soll.

    Was ich bisher "verstanden" habe:
    Wenn sich ein Benutzer einloggen möchte, kann er sich bei der Webseite mit Facebook einloggen -> Prüfen, on bei Facebook eingeloggt (Wenn Nein, erst Login) -> FacebookID hinterlegt, erfolgreicher Login / FacebookID nicht hinterlegt, hinterlegen der ID, erfolgreicher Login


    Wie sieht das aus, wenn sich ein Benutzer Registrieren möchte und wie kann ich das ganze für das WCF umsetzen? Ich hoffe, ihr könnt mit helfen.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Gnex ()

  • Schau dir dazu mal die OpenID Projekte von Roul an: community.woltlab.com/db/index…age=Project&projectID=388

    OpenID und OAuth sind die beiden bekanntesten Single Sign On Standards.
    Facebook nutzt OAuth, Google nutzt OpenID (oder inzwischen beides)

    Die Facebook ID hinterlegst du als Spalte beim Benutzer, machst einen MySQL Unique drauf und erlaubst den Login damit.
    OAuth mit Facebook ist relativ komplex, du musst auch den HTML Namespace (zumindest auf der Login Seite) erweitern, etc.

    Probier erstmal ein wenig rum, kannst gerne noch weitere Fragen dazu stellen.
    OpenID finde ich persönlich interessanter, da zumindest in DE wohl mehr Menschen einen Google Account haben - als einen Facebook Account.
    Leider ist das OpenID Paket von Roul nur auf Clientversion1 und er hat sich anscheindend die Mühe gemacht alles selbst zu programmieren. Ich würde lieber ein Third Party Open Source Plugin einbinden.
  • Okay, danke für den Tipp. hab mir OpenID angesehen und auch schon erfolgreich eingebaut.
    Nun werd ich mich mal an facebooik wagen ...

    Wenn ich das richtig verstanden habe, kann man sich damit auch - wie mit OpenID - externen daten und einer hinterlegten ID einloggen. Wenn die ID nicht gefunden (sprich nicht hinterlegt) ist, wird ein fehler ausgegeben und man kann sich nicht per Facebook einloggen.

    Ist das soweit richtig?

    Bei der Registrierung könnte man das so machen, dass der User entweder per externen Anbieter handelt und die Standart-Registrierung nutzt.
    Extern: Eingabe einer OpenID oder klick auf Facebook-Button // Wenn Daten, die für die Registrierung benötigt werden, vorhanden -> Registrierung und normale Aktivierung der Registrierung.

    Das wäre auch möglich oder habe ich etwas falsch verstanden?
  • also das Prinzip mit dem Login ist klar. Im Idealfall muss der Facebook Benutzer auch kein vollständiger Benutzer sein - er braucht z.b. kein Passwort. Er sollte einfach nur den Button drücken und anschließend angemeldet sein ;)
    Daten wie Vor- und Zuname erhältst du während dem Prozess automatisch.
    Hier nochmal die Schritt für Schritt Anleitung: wiki.developers.facebook.com/i…nect/Setting_Up_Your_Site

    Auf jeden Fall wird jeder Webmaster der dein Plugin installiert, seine eigene Facebook App erstellen müssen.

    Nachdem der Single Sign On funktioniert wäre dann der Activity Feed dran.
    Jedesmal wenn man ein Posting macht, könntest du automatisch auf der Facebook Profilseite einen Einrag machen.

    Für die Demo Applikation Run around gibts auch einen Download: wiki.developers.facebook.com/index.php/The_Run_Around
  • Hi,

    also ich hab mich nun mal ein bisschen hingesetzt und etwas eigenes geschrieben. Man kann nun seine FacebookID im UserCP hinterlegen, sofern man bei Facebook eingeloggt ist. Auch der Login (gnex.org/index.php?form=FacebookLogin) funktioniert schon fast, leider wieder eine weiße Seite und somit keine Fehlerdiagnose möglich.

    Den Button habe ich auch eingebaut (Klick auf "Anmelden") -> Allerdings steht dort nun "Diese Seite musst du mit Facebook verbinden."

    Das ganze ist noch sehr undynamisch und funktioniert nicht ganz automatisch. Was gemacht werden müsste, wäre dass das Hinterlegen der FacebookID (Bei mir Facebook-Verbindung genannt) auch funktioniert, wenn man bei Facebook nicht eingeloggt/angemeldet ist, so wie es in der API auch vorgesehen ist. Auch der Login sollte eigentlich ohne diese Form, nur auf Basis des Buttons, funktionieren.
  • Mittlerweile habe ich die Form weggenommen und sie durch eine Action ersetzt. Somit kann jeder User auf den Facebook-Button klicken, wickelt den Login mit Facebook ab und soll dann bei der Action laden, die den Login übernimmt -> So wäre es, wenn ich es richtig verstanden habe, auch angedacht > Eben ohne jegliche "User-Action".

    Leider funktioniert die "UserAuthFacebook" nicht:

    // Edit: Funktioniert

    Allerdings bekomme ich nun ein PermissionDenied, wenn ich die FacebookLoginAction aufrufe, obwohl ich nicht eingeloggt bin. Auch leitet er sofort weiter und nicht erst nach dem Facebook-Verbinden-Dialog.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Gnex ()

  • Kann ich machen. Allerdings ist nur der EventListener in die Package-Strucktur eingepflegt, alles andere nicht, da ich die Dateien zur Zeit direkt auf dem Server ändere.
    Mittlerweile funktioniert es auch ganz gut, nur leitet er innerhalb des PopUps auf "http://gnex.org/?session=JSON" weiter und macht eben nicht das, was er machen sollte:

    - PopUp schließen
    - Weiterleitung der Seite zur Action

    UPDATE
    Hochgeladen: trac.easy-coding.de/trac/wcf/browser/org.gnex.facebookauth

    UPDATE
    Tja, so wirklich möchte er das nicht machen, was in der API versprochen wird ... Er öffnet ein PopUp, obwohl sich dort ein JavaScript-Dialog öffnen sollte und auch die Weiterleitung nach dem Login funktioniert nicht.
  • Über das "wie" würde ich mir keine Gedanken machen. Das Problem hatte ich auch schon. Mal öffnet sich ein Popup, mal ein JavaScript Dialog.
    Das hängt u.a. mit dem Browser zusammen und damit ob du im Hintergrund schon in Facebook angemeldet bist oder nicht und vielleicht auch damit ob du der Applikation schon Rechte gegeben hast.

    Ansonsten werde ich mir das Plugin versuchen heute noch zu installieren, danach bin ich erstmal ein paar Tage nicht erreichbar.
  • Hallo,

    anscheinend stimmt mit der AuthClass etwas nicht:

    Quellcode

    1. <?php
    2. require_once(WCF_DIR.'lib/system/auth/UserAuthDefault.class.php');
    3. class UserAuthFacebook extends UserAuthDefault {
    4. /**
    5. * Loads instance of UserAuthFacebook instead of UserAuthDefault
    6. *
    7. */
    8. public static function loadInstance() {
    9. if (self::$instance === null) self::$instance = new UserAuthFacebook();
    10. }
    11. public static function loginManuallyFacebook($facebookID, $userClassname = 'UserSession') {
    12. $user = null;
    13. $sql = "SELECT userID FROM wcf".WCF_N."_user
    14. WHERE facebookIdentifier = '".escapeString($facebookID)."'";
    15. $row = WCF::getDB()->getFirstRow($sql);
    16. if (!$row['userID']) {
    17. require_once(WCF_DIR.'lib/system/exception/NamedUserException.class.php');
    18. throw new NamedUserException('Die angegebene Facebook-Verbindung konnte keinem Benutzer zugeordnet werden.');
    19. }
    20. $user = new $userClassname($row['userID']);
    21. return $user;
    22. }
    23. public function storeAccessDataFacebook(User $user) {
    24. HeaderUtil::setCookie('userID', $user->userID, TIME_NOW + 365 * 24 * 3600);
    25. HeaderUtil::setCookie('facebookIdentifier', $user->facebookIdentifier, TIME_NOW + 365 * 24 * 3600);
    26. }
    27. /**
    28. * @see UserAuth::loginAutomatically()
    29. */
    30. public function loginAutomatically($persistent = false, $userClassname = 'UserSession') {
    31. if (!$persistent) return null;
    32. $user = null;
    33. if (isset($_COOKIE[COOKIE_PREFIX.'userID']) && isset($_COOKIE[COOKIE_PREFIX.'facebookIdentifier'])) {
    34. $facebookID = $_COOKIE[COOKIE_PREFIX.'facebookIdentifier'];
    35. if ($facebookID) {
    36. $user = new $userClassname($_COOKIE[COOKIE_PREFIX.'userID']);
    37. HeaderUtil::setCookie('facebookIdentifier', '');
    38. } else {
    39. $user = new $userClassname($_COOKIE[COOKIE_PREFIX.'userID']);
    40. if ($user->facebookIdentifier == $_COOKIE[COOKIE_PREFIX.'facebookIdentifier']) {
    41. HeaderUtil::setCookie('facebookIdentifier', $user->facebookIdentifier, TIME_NOW + 600);
    42. }# else {
    43. # return null;
    44. #}
    45. }
    46. } else {
    47. $user = parent::loginAutomatically($persistent, $userClassname);
    48. }
    49. return $user;
    50. }
    51. }
    52. ?>
    Alles anzeigen



    Es erscheint folgender SQL-Fehler, weil die userID nicht gelesen werden kann:

    Quellcode

    1. Fatal error: Invalid SQL: SELECT wbb_user.*, avatar.*, wbb_user.userID AS wbbUserID, GROUP_CONCAT(DISTINCT whitelist.whiteUserID ORDER BY whitelist.whiteUserID ASC SEPARATOR ',') AS buddies, GROUP_CONCAT(DISTINCT blacklist.blackUserID ORDER BY blacklist.blackUserID ASC SEPARATOR ',') AS ignoredUser, (SELECT COUNT(*) FROM wcf1_user_whitelist WHERE whiteUserID = user.userID AND confirmed = 0 AND notified = 0) AS numberOfInvitations, GROUP_CONCAT(DISTINCT groups.groupID ORDER BY groups.groupID ASC SEPARATOR ',') AS groupIDs, GROUP_CONCAT(DISTINCT languages.languageID ORDER BY languages.languageID ASC SEPARATOR ',') AS languageIDs,user_option.*, user.* FROM wcf1_user user LEFT JOIN wbb1_1_user wbb_user ON (wbb_user.userID = user.userID) LEFT JOIN wcf1_user_whitelist whitelist ON (whitelist.userID = user.userID AND whitelist.confirmed = 1) LEFT JOIN wcf1_user_blacklist blacklist ON (blacklist.userID = user.userID) LEFT JOIN wcf1_avatar avatar ON (avatar.avatarID = user.avatarID) LEFT JOIN wcf1_user_to_groups groups ON (groups.userID = user.userID) LEFT JOIN wcf1_user_to_languages languages ON (languages.userID = user.userID) LEFT JOIN wcf1_user_option_value user_option ON (user_option.userID = user.userID) WHERE user.userID = GROUP BY user.userID LIMIT 1
    2. You get more information about the problem in our knowledge base: http://www.woltlab.com/help/?code=1064
    3. Information:
    4. error message: Invalid SQL: SELECT wbb_user.*, avatar.*, wbb_user.userID AS wbbUserID, GROUP_CONCAT(DISTINCT whitelist.whiteUserID ORDER BY whitelist.whiteUserID ASC SEPARATOR ',') AS buddies, GROUP_CONCAT(DISTINCT blacklist.blackUserID ORDER BY blacklist.blackUserID ASC SEPARATOR ',') AS ignoredUser, (SELECT COUNT(*) FROM wcf1_user_whitelist WHERE whiteUserID = user.userID AND confirmed = 0 AND notified = 0) AS numberOfInvitations, GROUP_CONCAT(DISTINCT groups.groupID ORDER BY groups.groupID ASC SEPARATOR ',') AS groupIDs, GROUP_CONCAT(DISTINCT languages.languageID ORDER BY languages.languageID ASC SEPARATOR ',') AS languageIDs,user_option.*, user.* FROM wcf1_user user LEFT JOIN wbb1_1_user wbb_user ON (wbb_user.userID = user.userID) LEFT JOIN wcf1_user_whitelist whitelist ON (whitelist.userID = user.userID AND whitelist.confirmed = 1) LEFT JOIN wcf1_user_blacklist blacklist ON (blacklist.userID = user.userID) LEFT JOIN wcf1_avatar avatar ON (avatar.avatarID = user.avatarID) LEFT JOIN wcf1_user_to_groups groups ON (groups.userID = user.userID) LEFT JOIN wcf1_user_to_languages languages ON (languages.userID = user.userID) LEFT JOIN wcf1_user_option_value user_option ON (user_option.userID = user.userID) WHERE user.userID = GROUP BY user.userID LIMIT 1
    5. error code: 1064
    6. sql type: MySQLDatabase
    7. sql error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'GROUP BY user.userID LIMIT 1' at line 13
    8. sql error number: 1064
    9. sql version:
    10. file: XYZ/wcf/lib/system/database/MySQLDatabase.class.php (118)
    11. php version: 5.2.6-1+lenny4
    12. wcf version: 1.1.1 pl 2 (Tempest)
    13. date: Fri, 01 Jan 2010 20:43:38 +0000
    14. request: /
    15. referer:
    16. Stacktrace:
    17. #0 XYZ/wcf/lib/system/database/Database.class.php(118): MySQLDatabase->sendQuery('SELECT ??wbb_us...', 1, 0)
    18. #1 XYZ/wcf/lib/data/user/User.class.php(63): Database->getFirstRow('SELECT ??wbb_us...')
    19. #2 XYZ/wcf/lib/system/session/UserSession.class.php(33): User->__construct('', NULL, NULL, NULL)
    20. #3 XYZ/lib/data/user/WBBUserSession.class.php(51): UserSession->__construct('', NULL, NULL)
    21. #4 XYZ/wcf/lib/system/auth/UserAuthFacebook.class.php(48): WBBUserSession->__construct('')
    22. #5 XYZ/wcf/lib/system/session/CookieSessionFactory.class.php(37): UserAuthFacebook->loginAutomatically(true, 'WBBUserSession')
    23. #6 XYZ/wcf/lib/system/session/SessionFactory.class.php(73): CookieSessionFactory->create()
    24. #7 XYZ/lib/system/WBBCore.class.php(200): SessionFactory->get()
    25. #8 XYZ/wcf/lib/system/WCF.class.php(98): WBBCore->initSession()
    26. #9 XYZ/global.php(18): WCF->__construct()
    27. #10 XYZ/index.php(7): require_once('XYZ/ht...')
    28. #11 {main}
    Alles anzeigen


    Der Fehler taucht nur ab und zu auf.
  • Die AuthClass habe ich mir nun vom WCF-Login abgeleitet und dementsprechend angepasst, nun läuft alles.
    Mittlerweile habe ich meinen Buschfunk auch mit Facebook verbunden und sitze nun an der Registrierung.

    Ich kann sagen, dass die API - wenn man sie einmal verstanden hat - eigentlich sehr einfach zu verstehen ist. ;)
    Sie bietet eine Hülle und Fülle an Möglichkeiten -> Eventuell werde ich noch weitere Dinge (wie z.B. Foro- und Videoupload) mit Facebook verbinden. Kommentare halte ich für weniger Sinnvoll, da ich dann alle Kommentarseiten bei mir ändern müsste.

    Erstmal zur Registrierung:
    - Ich habe keine Möglichkeit gefunden, mir die eMail-Adresse des Benutzers ausgeben zu lassen und so die eMail-Felder automatisch auszufüllen > Es geht nur eine von Facebook vergebene eMail-Adresse
    - Geburtsdatum und Geschlecht sind Profiloptionen; Ich habs mit $this->values['gender'] versucht, den Inhalt automatisch zu setzen > Ohne Erfolg
  • Klingt Klasse!!!

    E-Mails gibts über die Facebook API leider nicht. Aber du kannst dir die "proxied_email" holen und daran E-Mails versenden.
    Die E-Mails erscheinen dann im Facebook Account des Nutzers.

    Informationen dazu:
    wiki.developers.facebook.com/index.php/Users.getInfo
    wiki.developers.facebook.com/index.php/Proxied_Email

    Geburtsdatum und Geschlecht kannst du auch ändern. Dazu gibts die UserEditor Klasse

    Quellcode

    1. $user = new UserEditor($userID);
    2. $user->updateOptions(array(
    3. 'gender' => 1, // 0:wcf.user.profile.noDeclaration, 1:wcf.user.gender.male, 2:wcf.user.gender.female
    4. 'birthday' => '1980-01-01'
    5. ));
  • Hi,

    danke für den Tipp. An die "proxied_email" hatte ich auch schon gedacht, allerdings hat die - ich habe nicht gezählt - 100 und mehr Zeichen.

    Den UserEdtitor kann ich nicht nutzen, da ich die Daten - zumindest bei mir - schon bei der Registrierung vorausfüllen möchte, da sie bei mir Pflicht sind. Eine Abfrage wäre möglich, so dass bei pflicht die daten bei der Registrierung ausgefüllt werden.

    Für alle, die Interesse haben, gibts hier das Grundpaket schoneinmal fertig - Bitte erachtet dies als BETA: trac.easy-coding.de/trac/wcf/browser/org.gnex.facebook.auth

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von Gnex ()

  • wirklich cool.

    Allerdings würde ich auf den "facebookIdentifier" verzichten. Ich bin mir nicht sicher, ob die Facebook ID öffentlich einsehbar ist - oder ob sie bei jeder Facebook App die selbe ist.
    Somit könnte sich diese jeder in sein Cookie schreiben und wäre angemeldet.

    Ich persönlich werde die Registrierung auch ohne zusätzliche Daten ermöglichen. Single Klick Registrierung, Single Klick Login :)
    Vielleicht baust du noch eine Option dafür ein.

    Ich würde alles über die FacebookLoginAction machen - egal ob man auf Login oder Registrierung klickt.

    Quellcode

    1. if(facebook id bekannt)
    2. -> login
    3. else
    4. -> if(single click registrierung)
    5. -> user::create
    6. else
    7. -> headertil::redirect(page=Register)
  • Achso - Du würdest vorschlagen, dass einfach geprüft wird, ob man für die App (Webseite) bei Facebook freigeschaltet ist und somit auf den "facebookIdentifier" verzichten. Der "facebookIdentifier" ist die UserID, die bei Facebook vergeben ist. Dann müsste man aber zur UserID irgendeinen anderen Identifier setzen, wie es die UserAuth vom WCF vor macht.

    Soll ich den Single-FacebookLogin/die Single-FacebookRegistrierung so verstehen, dass der Identifier dem WCF bekannt ist oder das die App bei Facebook für den User hinterlegt ist?

    Zwei Beispiele:
    - App für User nicht bekannt -> Registrierung mit App-Freischaltung -> Auf Seite angemeldet
    oder
    - Identifier nicht bekannt -> Registrierung mit Identifier-Setzung -> Auf Seite angemeldet
  • Ich will den facebookIdentifier nicht abschaffen. Aber ihn direkt aus dem Cookie auszulesen ist unsicher.

    Schau nochmal in den Woltlab Code, dort wird ein Salz genutzt, der das ganze absichert.
    Den existieren Salz vom Woltlab Login kannst du aber nicht verwenden, da er sich bei jedem Passwort Update ändert. (EventListener dafür würde ich nicht anlegen)
    Du müsstest also deinen eigenen Salz einführen (Daten Overhead?)

    Ich würde den Facebook Login aber nur als Wrapper für den Woltlab Login betrachten.
    LoginManually überschreibst du und wickelst ihn über Facebook ab. Bei Erfolg sollen weiterhin UserID und Passwort ins Cookie gespeichert werden.
    Aber LoginAutomatically würde ich nicht antasten. So funktioniert der Login weiterhin über UserID, Passwort und Salz.

    Zu deiner zweiten Frage: ich persönlich habe die Variante unten gemeint. App Freischaltung ist Voraussetzung für den Facebook Login.
  • Ich habe jetzt einmal die klare FacebookID, den Hash und einen Salt zum Hash im Update. Die klare FacebookID benötige ich, da ich beim Logincheck ersteinmal die UserID auslesen muss -> Nun wird aber nur noch ein Hash im Cookie gespeichert.

    - Sofern FacebookID bekannt, nicht in der Datenbank vergeben und App bei Facebook für den User nicht bekannt folgt eine automatische Registrierung (Wenn ein Fehler auftaucht > Weiterleitung zur manuellen Registrierung)
    - Wenn FacebookID bekannt und in der DB vorhanden folgt ein Login (Falls App nicht freigeschaltet erfolgt dies durch den User)
    - Wenn FacebookID nicht bekannt folgt eine Weiterleitung zum RegisterFormular