{"id":4102,"date":"2012-01-07T17:35:27","date_gmt":"2012-01-07T16:35:27","guid":{"rendered":"http:\/\/notizblog.org\/?p=4102"},"modified":"2020-03-24T14:26:00","modified_gmt":"2020-03-24T13:26:00","slug":"browserid-as-easy-as-copy-and-paste","status":"publish","type":"post","link":"https:\/\/notiz.blog\/2012\/01\/07\/browserid-as-easy-as-copy-and-paste\/","title":{"rendered":"BrowserID &#8211; as easy as copy &#038; paste"},"content":{"rendered":"\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"500\" height=\"140\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" src=\"https:\/\/notiz.blog\/wp-content\/uploads\/2012\/01\/BrowserID.jpg\" alt=\"BrowserID\" class=\"wp-image-4104\" srcset=\"https:\/\/notiz.blog\/wp-content\/uploads\/2012\/01\/BrowserID.jpg 500w, https:\/\/notiz.blog\/wp-content\/uploads\/2012\/01\/BrowserID-480x134.jpg 480w\" \/><\/figure><\/div>\n\n\n\n<p>Ich schreibe gerade einen Artikel f\u00fcr das <a href=\"http:\/\/t3n.de\/\">t3n Magazin<\/a> \u00fcber aktuelle Sign-In-Mechanismen und hab mir in dem Zuge BrowserID mal etwas genauer angeschaut. Ich bin wirklich extrem \u00fcberrascht mit wie wenig Arbeit es sich in z.B. WordPress einbauen l\u00e4sst.<\/p>\n\n\n\n<p><a href=\"https:\/\/web.archive.org\/web\/20120619053844\/https:\/\/browserid.org\/\">BrowserID<\/a> besteht eigentlich nur aus einem <abbr title=\"JavaScript\">JS<\/abbr>-File,ein paar Zeilen <abbr title=\"JavaScript\">JS<\/abbr>-Code:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"https:\/\/browserid.org\/include.js\"<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"text\/javascript\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">script<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"text\/javascript\"<\/span>&gt;<\/span><span class=\"actionscript\">\nnavigator.id.get(<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span><span class=\"hljs-params\">(assertion)<\/span> <\/span>{\n    <span class=\"hljs-keyword\">if<\/span> (assertion) {\n        <span class=\"hljs-comment\">\/\/ This code will be invoked once the user has successfully<\/span>\n        <span class=\"hljs-comment\">\/\/ selected an email address they control to sign in with.<\/span>\n    } <span class=\"hljs-keyword\">else<\/span> {\n        <span class=\"hljs-comment\">\/\/ something went wrong!  the user isn't logged in.<\/span>\n    }\n});\n<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">script<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>und dem anschlie\u00dfenden Verifizieren der <code>assertion<\/code>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">$ curl -d <span class=\"hljs-string\">\"assertion=&amp;audience=https:\/\/mysite.com\"<\/span> <span class=\"hljs-string\">\"https:\/\/browserid.org\/verify\"<\/span>\n{\n    <span class=\"hljs-string\">\"status\"<\/span>: <span class=\"hljs-string\">\"okay\"<\/span>,\n    <span class=\"hljs-string\">\"email\"<\/span>: <span class=\"hljs-string\">\"lloyd@example.com\"<\/span>,\n    <span class=\"hljs-string\">\"audience\"<\/span>: <span class=\"hljs-string\">\"https:\/\/mysite.com\"<\/span>,\n    <span class=\"hljs-string\">\"expires\"<\/span>: <span class=\"hljs-number\">1308859352261<\/span>,\n    <span class=\"hljs-string\">\"issuer\"<\/span>: <span class=\"hljs-string\">\"browserid.org\"<\/span>\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Den ausf\u00fchrlichen Ablauf der Authentifizierung findet ihr auf <a href=\"https:\/\/github.com\/mozilla\/browserid\/wiki\/How-to-Use-BrowserID-on-Your-Site\">Github<\/a>.<\/p>\n\n\n\n<p>Um BrowserID in WordPress zu integrieren l\u00e4dt man also zuerst den <abbr title=\"JavaScript\">JS<\/abbr>-Code in den Login Header:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ add the BrowserID javascript-code to the header<\/span>\nadd_action(<span class=\"hljs-string\">'login_head'<\/span>, <span class=\"hljs-string\">'bi_add_js_header'<\/span>);\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">bi_add_js_header<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n  <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">'&lt;script src=\"https:\/\/browserid.org\/include.js\" type=\"text\/javascript\"&gt;&lt;\/script&gt;'<\/span>;\n  <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">'&lt;script type=\"text\/javascript\"&gt;'<\/span>.<span class=\"hljs-string\">\"\\n\"<\/span>;\n  <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">'function browser_id_login() {\n    navigator.id.get(function(assertion) {\n      if (assertion) {\n        window.location=\"'<\/span> . get_site_url(<span class=\"hljs-keyword\">null<\/span>, <span class=\"hljs-string\">'\/'<\/span>) .<span class=\"hljs-string\">'?browser_id_assertion=\" + assertion;\n      } else {\n        \/\/ do nothing!\n      }\n    })\n  };'<\/span>.<span class=\"hljs-string\">\"\\n\"<\/span>;\n  <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">'&lt;\/script&gt;'<\/span>;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>und platziert den BrowserID-Button auf der Login-Seite:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">\/\/ add the login button\nadd_action('login_form', 'bi_add_button');\nfunction bi_add_button() {\n  echo '<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">a<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"#\"<\/span> <span class=\"hljs-attr\">onclick<\/span>=<span class=\"hljs-string\">\"return browser_id_login();\"<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">img<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">\"https:\/\/browserid.org\/i\/sign_in_blue.png\"<\/span> <span class=\"hljs-attr\">style<\/span>=<span class=\"hljs-string\">\"border: 0;\"<\/span> \/&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">a<\/span>&gt;<\/span><span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span>';\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Nach dem klick auf den Button \u00f6ffnet sich das Autorisierungs-Fenster von BrowserID und nach dem erfolgreichen Sign-In wird die gerade implementierte Methode <code>navigator.id.get(function(assertion) {}<\/code> aufgerufen.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter\"><img loading=\"lazy\" decoding=\"async\" width=\"500\" height=\"412\" sizes=\"auto, (max-width: 500px) 100vw, 500px\" src=\"https:\/\/notiz.blog\/wp-content\/uploads\/2012\/01\/BrowserID-login-window.jpg\" alt=\"BrowserID login window\" class=\"wp-image-4111\" srcset=\"https:\/\/notiz.blog\/wp-content\/uploads\/2012\/01\/BrowserID-login-window.jpg 500w, https:\/\/notiz.blog\/wp-content\/uploads\/2012\/01\/BrowserID-login-window-480x395.jpg 480w\" \/><\/figure><\/div>\n\n\n\n<p>Im n\u00e4chsten Schritt mu\u00df man die erhaltene <code>assertion<\/code> \u00fcber BrowserID.org verifizieren. Da ich den notwendigen <code>POST<\/code> nicht \u00fcber JavaScript absetzen will, leite ich einfach auf eine Seite weiter und \u00fcbergebe die erhaltene <code>assertion<\/code> als GET-Paramater.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\"><span class=\"hljs-keyword\">if<\/span> (assertion) {\n  <span class=\"hljs-built_in\">window<\/span>.location=<span class=\"hljs-string\">\"' . get_site_url(null, '\/') .'?browser_id_assertion=\"<\/span> + assertion;\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Jetzt kann der POST bequem \u00fcber WordPress abgesetzt werden.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ the verification code<\/span>\nadd_action(<span class=\"hljs-string\">'parse_request'<\/span>, <span class=\"hljs-string\">'bi_verify_id'<\/span>);\n<span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">bi_verify_id<\/span><span class=\"hljs-params\">()<\/span> <\/span>{\n  <span class=\"hljs-keyword\">global<\/span> $wp_query, $wp, $user;\n\n  <span class=\"hljs-keyword\">if<\/span>( array_key_exists(<span class=\"hljs-string\">'browser_id_assertion'<\/span>, $wp-&gt;query_vars) ) {\n    <span class=\"hljs-comment\">\/\/ some settings for the post request<\/span>\n    $args = <span class=\"hljs-keyword\">array<\/span>(\n      <span class=\"hljs-string\">'method'<\/span> =&gt; <span class=\"hljs-string\">'POST'<\/span>,\n      <span class=\"hljs-string\">'timeout'<\/span> =&gt; <span class=\"hljs-number\">30<\/span>,\n      <span class=\"hljs-string\">'redirection'<\/span> =&gt; <span class=\"hljs-number\">0<\/span>,\n      <span class=\"hljs-string\">'httpversion'<\/span> =&gt; <span class=\"hljs-string\">'1.0'<\/span>,\n      <span class=\"hljs-string\">'blocking'<\/span> =&gt; <span class=\"hljs-keyword\">true<\/span>,\n      <span class=\"hljs-string\">'headers'<\/span> =&gt; <span class=\"hljs-keyword\">array<\/span>(),\n      <span class=\"hljs-string\">'body'<\/span> =&gt; <span class=\"hljs-keyword\">array<\/span>(\n        <span class=\"hljs-string\">'assertion'<\/span> =&gt; $wp-&gt;query_vars&#91;<span class=\"hljs-string\">'browser_id_assertion'<\/span>], <span class=\"hljs-comment\">\/\/ the assertion number we get from the js<\/span>\n        <span class=\"hljs-string\">'audience'<\/span> =&gt; <span class=\"hljs-string\">\"http:\/\/\"<\/span>.$_SERVER&#91;<span class=\"hljs-string\">'HTTP_HOST'<\/span>] <span class=\"hljs-comment\">\/\/ the server host<\/span>\n      ),\n      <span class=\"hljs-string\">'cookies'<\/span> =&gt; <span class=\"hljs-keyword\">array<\/span>(),\n      <span class=\"hljs-string\">'sslverify'<\/span> =&gt; <span class=\"hljs-number\">0<\/span>\n    );\n\n    <span class=\"hljs-comment\">\/\/ check the response<\/span>\n    $response = wp_remote_post(<span class=\"hljs-string\">\"https:\/\/browserid.org\/verify\"<\/span>, $args);\n\n    <span class=\"hljs-keyword\">if<\/span> (!is_wp_error($response)) {\n      $bi_response = json_decode($response&#91;<span class=\"hljs-string\">'body'<\/span>], <span class=\"hljs-keyword\">true<\/span>);\n\n      <span class=\"hljs-comment\">\/\/ if everything is ok, check if there is a user with this email address<\/span>\n      <span class=\"hljs-keyword\">if<\/span> ($bi_response&#91;<span class=\"hljs-string\">'status'<\/span>] == <span class=\"hljs-string\">'okay'<\/span>) {\n        $userdata = get_user_by(<span class=\"hljs-string\">'email'<\/span>, $bi_response&#91;<span class=\"hljs-string\">'email'<\/span>]);\n        <span class=\"hljs-keyword\">if<\/span> ($userdata) {\n          $user = <span class=\"hljs-keyword\">new<\/span> WP_User($userdata-&gt;ID);\n          wp_set_current_user($userdata-&gt;ID, $userdata-&gt;user_login);\n          wp_set_auth_cookie($userdata-&gt;ID, $rememberme);\n          do_action(<span class=\"hljs-string\">'wp_login'<\/span>, $userdata-&gt;user_login);\n\n          wp_redirect(home_url());\n          <span class=\"hljs-keyword\">exit<\/span>;\n        } <span class=\"hljs-keyword\">else<\/span> {\n          <span class=\"hljs-comment\">\/\/ show error when there is no matching user<\/span>\n          <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"no user with email address '\"<\/span> . $bi_response&#91;<span class=\"hljs-string\">'email'<\/span>] . <span class=\"hljs-string\">\"'\"<\/span>; \n          <span class=\"hljs-keyword\">exit<\/span>;\n        }\n      }\n    }\n    \n    <span class=\"hljs-comment\">\/\/ show error if something didn't work well<\/span>\n    <span class=\"hljs-keyword\">echo<\/span> <span class=\"hljs-string\">\"error logging in\"<\/span>; \n    <span class=\"hljs-keyword\">exit<\/span>;\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Gibt es einen User mit der entsprechenden E-Mail &#8211; Adresse wird er eingeloggt, falls nicht, wird ein Fehler ausgegeben.<\/p>\n\n\n\n<p>Bei der Demo hab ich mir aus Zeitgr\u00fcnden ein wenig Code bei Marcel Bokhorst geliehen, dessen <a href=\"http:\/\/wordpress.org\/extend\/plugins\/browserid\/\">BrowserID-Plugin<\/a> wesentlich ausgereifter und vollst\u00e4ndiger ist als der kleine Demo-Code den ich hier zusammengest\u00fcckelt habe.<\/p>\n\n\n\n<p>Wenn euch das zu schnell ging und ich auf einige Details nicht gen\u00fcgend eingegangen bin, k\u00f6nnt ihr gerne fragen \ud83d\ude42<\/p>\n\n\n\n<p>Ich habe den kompletten Code \u00fcbrigens auch auf <a href=\"https:\/\/gist.github.com\/1574995\">Github<\/a> hochgeladen&#8230; das ist einfacher als sich alles zusammen zu kopieren.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Ich schreibe gerade einen Artikel f\u00fcr das t3n Magazin \u00fcber aktuelle Sign-In-Mechanismen und hab mir in dem Zuge BrowserID mal etwas genauer angeschaut. Ich bin wirklich extrem \u00fcberrascht mit wie wenig Arbeit es sich in z.B. WordPress einbauen l\u00e4sst.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"webmentions_disabled_pings":false,"webmentions_disabled":false,"activitypub_content_warning":"","activitypub_content_visibility":"","activitypub_max_image_attachments":4,"activitypub_interaction_policy_quote":"anyone","activitypub_status":"","footnotes":""},"categories":[2],"tags":[949,5171,705,423,181,792,57],"class_list":{"0":"post-4102","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-web","7":"tag-browserid","8":"tag-fediblog","9":"tag-mozilla","10":"tag-openid","11":"tag-plugin","12":"tag-singlesignon","13":"tag-wordpress","14":"h-entry","15":"hentry"},"_links":{"self":[{"href":"https:\/\/notiz.blog\/wp-api\/wp\/v2\/posts\/4102","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/notiz.blog\/wp-api\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/notiz.blog\/wp-api\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/notiz.blog\/wp-api\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/notiz.blog\/wp-api\/wp\/v2\/comments?post=4102"}],"version-history":[{"count":0,"href":"https:\/\/notiz.blog\/wp-api\/wp\/v2\/posts\/4102\/revisions"}],"wp:attachment":[{"href":"https:\/\/notiz.blog\/wp-api\/wp\/v2\/media?parent=4102"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/notiz.blog\/wp-api\/wp\/v2\/categories?post=4102"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/notiz.blog\/wp-api\/wp\/v2\/tags?post=4102"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}