{"componentChunkName":"component---src-templates-blog-list-template-js","path":"/152","result":{"data":{"allMarkdownRemark":{"edges":[{"node":{"excerpt":"In an expansive article for Harvard Business Review, McKinsey and Company analysts have described Customer Experience as “cumulative…","fields":{"slug":"/identity/customer-identity-preference-trends-q1-2016/"},"html":"<p>In an expansive <a href=\"https://hbr.org/2013/09/the-truth-about-customer-experience\">article for Harvard Business Review</a>, McKinsey and Company analysts have described Customer Experience as “cumulative experiences across multiple touch points and in multiple channels over time.” But if somebody asks for a mathematical definition of something as psychological as Customer Experience, one could blurt out: “Customer Experience is the integral from the beginning to the end of the customer-business relationship of the integral of individual user experiences across all touch points.” Why someone would ask for a mathematical definition is a discussion for another day.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 250px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 129.2%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAaCAYAAAC3g3x9AAAACXBIWXMAAC4jAAAuIwF4pT92AAAGxUlEQVRIxzVVWVRVRxZ9H/3Rq5cf3UEUfDKKEKK9cBHsGNOJMRqnJ8ggSpzSDihRG+04ABJkUiYhgjIFbDsqKkhHWElwAAEV6PAMoMzIjAyPSRmUC75I7d71ktRaZ9W9dW/tc2qfXeeo5m4I18/bGAnbTVFC7RwKm40R+PCLZJjy2YLrNltiYbP9ayz6/Cz2J+XD/rMYzHU7BbVLGEw0wTBzP405zqHCdH0ITNeHKiq1Jljv7H8Fwde1wmn3eZi7hGLB5ihYbYrG/K1xnKNgt/M83tuXjH1n8+C4KwH2e5JgvTkac13DYbk5RjoXZnTCd0W1wCtG/4lvOk4SUM1F43XBmE8AE+cwvLXyBExdT2Plufuw9U7Fgi1nMIuRzXCPxJ/5n9GngVj0j3i87RUt1ATnaRWVk0+yfs3R/8Ar/L9iye5z+Ov2OCz9ZxrsGeWHRy8ZzHFvMpy8E3EwuQAfHEjFvB3xWEgg07VB2BqRA01AhrD5PB72O88pqqf9L0VT7yhadONCNzqF2vYh1LYNomd4As26MTT2jaGuaxgdAy9Rx291HUOGuWvwJY6m3DGcwJr8W5IaS88oRTX8So+XeoiWvlHsDs/ER3sS8JH3ORz+OtcAOjYloAcQn1UKly8vQDc6iefKG/zCtcC0u5ix3B8OPqnC2itGJlFRDb3Si2fc+O62WKE5lIZ7Fe24Xd6M93eexar9yRidnIbvmZtQr/4K1kxYKx33j7+WQSDsaglmM8L3j10hIPnVhCgq/o9vcsphTgn0vZjEFD1L7/Wdw5hF0nMe1CPvf0+RVVANB69otJGGQaJN8KfQjBKYesbAeO1JYbctDiu/vKioJEBgyi0s3RWP8alpPHs+gd6RSQyMTcGOGjt/owxy5D9qhR1VICMc+A0w7FopbH3SYeJ2WthtjYXm+CVFNfEGuFFYA+MVAagh2b+Pwsp2vEV+CkmBHGW13Vi4KRJDBJMcyn1+ybfwp2XHYbImSDAhsPCKUVTS23O68wq4hHc8IxB9uRjh/y6ArfspHIn/HtyLR419CEq6hZmfBOBCjhbNvSN4TSf+Kbeh9ow2ZNn6szNQSx0OkOBhAg6O6xGfWQKPYxexPSgDZuRUAks+r91+DO+QTPwrNheHo2+ioklnWA9IvQObXYmw8IgQ1qTHwvVXQNFPvki0eP1bQuQoqurACp9EFJA7OQRNykf+Y+CQkfsn52HGx34wWXdSLPO9gL8fTFdUkg8dxZZf0oSi8hbcJ2faum48fNSGEoI+IJfamm4UE7iT4pZg/TzNJAGjcivh4JcFc/cIMZ86NJdH7h6aEK28KQ8r20U5iS993Imf63tR2TKIQjrIL2smaAdKaX28Sb0vFHToxjFCmgIvFkHtFQdLHtmKxcLAocY37Ze1B1PhFnRdOPtfhnd0Dtz9LmMj7+i6w+lYdSAFzse/hRS964nLcAm4QsvAir2JcNyZAKNVJySQeGd3ImatCVJUP5Y2vbmjbUHuw0aRmV+NnKI6ZHPOYiKyC2uRW1yPq3mVyKDdKKpFdkkjrhfXIa+0CdtOXpWihuWGMGHDCM09IhRVe9+oaOt9gfo2nXjS3IeG9gHUtuhQQ2to76ek9HzvQ1VjN5q7hlDztBd1rTqMjE/iBLM8n0VBc+RbsXgPS956Xr3vSxqnb9EbsylulzXhHsmXoi78uc1gBYz+7k/Nhptyl5zK798xwh1hmVi0Iw6LWZRDMsrFx4cuYOZqHrmioXtaW9MJzuKn6g4m5BnKOVc19qCaET9u6jEk4BX1NMaLL6VT3/UcputCYEHtvcs6ucQ7SbzNI89xCVNUZdVd02W1z/DwcYcorenCA0qlmBEajM8/aluRdb8e3z1oQHbpU+QyypSbWvaWWENbsJQ9xf20sPq9fBVXtE0XsFyVPOkUEvjeoxZoG3rQ0D2CHhaJhB+q8IflgfjjMj/M9oiE8YZTMFobDMcjV6T+oHYOASVj6CkzPw1UVC09o9MVTX0oreoQFfU9kPakWYeuoQmMvnqDeNa893xSsDk8G/OYANnd/sbyb8uIzDwiYLvjrOHq8bbITqioluxN1H9wKB2+CXnCjXqzY0Vx3JOIxfuSsNQnGQ7cEPNDDa5W6rCMvWYOI7GV3dAz0tBOzVll2O2ENdeMV3+lqOx90vXGLuGw2h4vrLbEYaFbOJZ7J8CaXYzcYLYmBBq22QNsUE6Uhjl7tewfsmcb8/tfXE/BxCVMLPwi7dekOB27ppdejDzPCDNeo5XsKa4Hk+DASC240YzAs3lM41WBWLL/G0Njl8eTRzeizSSnjFTM4TO/Kf8Hq+GS9o6LLdQAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"Q1 2016 featured\"\n        title=\"Q1 2016 featured\"\n        src=\"/static/5fc5c5ffde6b586e913dd01591c4796e/63868/Q1_2016_featured.png\"\n        srcset=\"/static/5fc5c5ffde6b586e913dd01591c4796e/63868/Q1_2016_featured.png 250w\"\n        sizes=\"(max-width: 250px) 100vw, 250px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span>You can choose the definition you like (we bet you will go with the McKinsey guys) but the point here is about what customers want and what satisfies them. Often the seemingly simpler things matter the most, particularly when these things figure quite a number of times. For instance, let’s say you provide the means for your customers to sign in using their social identities. Owing to obvious constraints, you can only provide for direct links to login with two or three social identities. If your customers choice of identity doesn’t figure in your top two or three list, they are forced to go to another page to look for their choice of identity. It’s a simple thing made difficult because of the lack of knowledge of what your customers preferences are.</p>\n<p>To know what your customers like and prefer only makes things simpler and clearer. Customer preferences don’t just alter minor things but can also influence long term strategy. Analysis of customer preferences is critical to businesses.</p>\n<p>But don’t worry. We got you covered.</p>\n<p>The LoginRadius Analytics team analyzed customer behavior data from over 160,000 websites, powered by our <a href=\"https://www.loginradius.com/\">Customer Identity Management (CIM) platform</a>, and compiled analysis about what customers preferences are and how those preferences vary with specific demographic characteristics. Our Customer Identity Preference Trends Report for Q1 2016 is now available for download <a href=\"https://www.loginradius.com/resource/customer-identity-preference-trends-2016/\">here</a>. And while you download the report, we will give you a sneak peek into what customers generally want.</p>\n<p>Once again, Facebook held its forte and emerged as the most preferred social identity for logging into websites. Google+ followed in second place but with a much smaller share in the social identity space. About 94% customers use their Facebook or Google+ identities to sign into websites which is mammoth number telling you these two networks should be the top on your list.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 70.3076923076923%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAYAAAAvxDzwAAAACXBIWXMAAC4jAAAuIwF4pT92AAADqklEQVQ4y1WTe0xTdxTHT1vZJllIHA8plEeF9fahTFYdYwYb5+bmeLS0YiSSOXn0In2BwFBApF0rYWY60BhtHEu0SIXe2wsWozCzMOdm5tRs2WbchqG2GCWZ239uKfHsd1t88Eu++Z5zf+f3yf2dXw4AWRQbAjkTAorhPayUs6E35Wy4gMQq4mtJXkAkJ/EbROtI3RrivHKI+DOwaPHAKCwGFlJMOE4ezcMJ5HsR0SoSq4nnUWdnlpJ9kcIXXKIcviOCEILWfgxomo5qEfCJFP5ZUHCzfCwioGUE8rLs9B9J1EgwgQo8EKS83ingz2kOMrCvYgPUNpifAe0OJ9jtTmg7cAicXd1g7D8NRX1TsOrYTch1/wJ5PyPk9F+HrPYJWHH4GlBZtZBpYQFaglBCO+JajdsEdXS9YDFwQR3OXnC32UDluQEp3mnIbBkXpFcPgarj4ouZjaNdGbbRqxlW7keJdfTIa42nsveYKyU1dIOSpo0KI00vjQHtPMzFA0V7nQdTmdYdyUr3DY1k4Pc+ME0B1TAiTLNwF8UWP0qsHGYSZdg4zDL5/nx/4940afUgFNL9QiQtWPhDF3TbeaArvt3RKxnr+jBRc+BCeX7P1OSyej+kWznjqy0BXLnn/H/ZTWPzSbbx+WRr4JGsKYC5jivu9dZheMvMiOAKPgeMXVnQ2dmTcuLUx0nby92lhs0D3EsmDlLN/pGiTyZx86dfR3Kbz6GmYeCx2XJ4vs+2H1l610+oTngBCxLgctXWZ0AiUbfDlda+v0cSONqYqK7zlMh2nvWLm84B6dtQOrluqpmLSC0MXq0oe/xIq55/WLoW/ylW3/ytsnjJPf0GwPdWwtMedseggrZ9rrRvPI5X5IYenbi497y4+QIPrOR7JrGNRXKsTOT7LaWRh/Vb/g1t24R3y9Z9dqekEPBdhbC1tiYGzBueFsFlFNZ87olvdh2SOL/wJu7YtVtbVWPyrz/+VVwHaTZ5YS8BotTG4rdbtTinLcRgueYHd+1OaUVjm6zOZF1dtbsjGRAFsZEj46Ng7oLKNwP53lsA18ibIYJ87D5Qg9OQfWYGlld7dVLa++WvJZpB1Ihpfv8j96VoHdxGWDE0HZ00HqgnQD3vCzLI2HvlOdxcGZkSPZkWA7+vnPx7o2rir3fiL+Em8qJvS7kHunw2aFgzPqejPLd0sjO39Xw9P174RHLe2XDUn4rkz9eQm6DSF0SZL4SrR2fxg4n7KD/+HeaevE5qZ/F/HvHsWrJdo+UAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"2016-Q1-Social-Login_Preference-Users\"\n        title=\"2016-Q1-Social-Login_Preference-Users\"\n        src=\"/static/0fe71d3e801eaf5933ab70b04217118e/e5715/2016-Q1-Social-Login_Preference-Users.png\"\n        srcset=\"/static/0fe71d3e801eaf5933ab70b04217118e/a6d36/2016-Q1-Social-Login_Preference-Users.png 650w,\n/static/0fe71d3e801eaf5933ab70b04217118e/e5715/2016-Q1-Social-Login_Preference-Users.png 768w,\n/static/0fe71d3e801eaf5933ab70b04217118e/7510d/2016-Q1-Social-Login_Preference-Users.png 2119w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>But if your target audience is above 35 years, you will have to think again because only a third of all the customers who used their <a href=\"https://www.loginradius.com/social-login/\">social identity to sign into websites</a> were aged above 35 years. If that is not all, Social Login from desktop computers (both Windows and Mac) ran up to a mammoth 80% of all which should tell you that if you are targeting mobile, it should be the mobile app.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 75.99999999999999%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAAC4jAAAuIwF4pT92AAADVklEQVQ4y3WUWUwTYRCAZxuiD5oIJj6grfag3e3SUlArEDDGKCGtgCZEY4zPGsSIxwOiYjDcnkF7qBzGC2XLFuUKKgKKSEFNoKCJBtpCC1GjvvhmStf5t9RA1D/5MpPd/b/MzL+7APOLcfqRANA8Rt6vop2BjUgS5mqE5MkYNXh/Az6XhqwmzyMUiX8tURYmBjemMGFZKs0HjESOeQbGOIzJeC9lXrp0XrpYZuK8EO/wgq5pEgwO71IdP72C5f3RmvavK9nmyVVJ9S+W0C2za1C2DDdHE7BSUqHkv8It1/th69Uu2H57BLY2T0Fa3TBszqtekbE/P33z4epV62u6YM2IIHbB/IPFQqwuK/8MZOUVwY5qTmU+WZN75Lx1udY2bmGto3Na25hFax2HpKrOqER7H6jbvuGcp8msw+D8Fy0z5wNz0yRlfjiBuZczcR4hh58qoS3ue6xtTGCtbj6hxgUgCBT0CJSAewjKyiH45zJjhSaHj0JI7DRxPiGbn7pAW0YbWJtbwEofxDb+ggINxKAUClQAe7Ylw84sM2Tn5IjISl8vFPpIZRRCYhvOlAirscJbRMjax2+pzvXto0uevVOV9ReyZzsAZgQJdAvUiTiAUzIAWdlCIRFhhaLY4WtfLMSW7WM35RVDNkXVG0FROdQjPe8mLUvgpQCiUAogjQgPHioQhZGWMV8gHI0IaxXlg5eUFS4i5OXFT/RMYVO5srgrU3+8AfTH6rHlgbDwQF4BiLPjPJS5yUNeodZ5YRUK6/FAiPBGRIgH0SgtfX1NWjYoYFXPpeUuQKg/FeKxS3TIJmcgau+jz0Tea3JMEeE12urmcH5kho2KCtd1ZdWwgLTLygYssvJBAefWG3O0G1S176M09yfISy6JfG4iyo6fkNPwLtdUO3xx952R9PjK3kxdZc9lw8X+7erC9i1xRW2XNUUd2fLT3anrClsvyIu6dimc30HX+AE0+JWJLziKjCK838i0zBrX3v2gj73yVC/nvAn0w48Gtb1Hr3FO6xneY2Dq+/VM80SC9smPePa2S6frmI03PJ41ah98Mmo4jxGFRtJyUMQZCNLhGGJaZkIY58JgzgdC+JOYozGnyTXeH1LjtcTHgdCOZ1+CjP1VMK7uLe6dCf4GWYYDbpq31gAAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"2016_Q1_Social-Login_Preference-Age\"\n        title=\"2016_Q1_Social-Login_Preference-Age\"\n        src=\"/static/72a4c673a1d294cf4a9ea66c70161408/e5715/2016_Q1_Social-Login_Preference-Age.png\"\n        srcset=\"/static/72a4c673a1d294cf4a9ea66c70161408/a6d36/2016_Q1_Social-Login_Preference-Age.png 650w,\n/static/72a4c673a1d294cf4a9ea66c70161408/e5715/2016_Q1_Social-Login_Preference-Age.png 768w,\n/static/72a4c673a1d294cf4a9ea66c70161408/7510d/2016_Q1_Social-Login_Preference-Age.png 2119w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>Facebook did lose some ground to Google+ in Q1 2016 but not by an amount that would worry the social giant. Nevertheless, Google+ will be heartened by its performance. Sharing, however, is a different story and not one that the search giant would be really happy about. More than half of the social content on the Web is hosted on Facebook while, like in Q4 2015, Twitter comes in second with 16%. Email is not be discounted again as it has notched up the third place and is expected to go strong in the coming quarters too.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 77.84615384615385%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAYAAAAWGF8bAAAACXBIWXMAAC4jAAAuIwF4pT92AAAD5UlEQVQ4y22Ue0xTVxjAPy5EKUxxDOXR4up43BZtaQutfXDtFs2YCSTWP4RicdlDgkw3lT8IM3RDjC7xBUw6wA7iEJzQFpiAxcc2t8wwrMmWZTMpcUKvMDIFBogMhJ59t1pkhi/53XNO7rm/79x77ncAnoXIcX8RLND2+2rawapwLEeSERpRImt9c+zP5y8ZtJ31E4ZIELnIzmoQpdjObhTZBpR0S7+Ktg1wSeLwfqA/+ZIhah30ZwwRd44IJZfHYiUONg4fEK5zDEbJ24dEmh9mY5OuT8eiNFFk8wTSzf2ASZYWyvoISK8+AlnrEFAA1BVC4K0L9yC1BV/pUAcQHGOs4gOErf24EeILa0Dw7lGIzjuxtHC1Ohtk71XA1hM30AcRUmOJOuerO8eNNvbbm4XF18aztnaeN+7UcmKJZDMvPEEXuDJeB6HCjRDCl/v4X8gzyyDL4grYXtELu7smovJaPX1mp4fsaWO9v5lLx2bzjVPVlVXuYxbrfpweHpeaHrIsRgahiF+4IE3beRZ0ObW+/utdU9zYua3s+tC+tv7xfOfwjP1k/QPnJyW/nGluJacbvibm7u8VhWWfwd+PRwNWxiRDCEp5/KcsCBHK15qsW3TGGqLNrnm0t2Ng9Ev3Y/LjA+98xU93vSfLLSMX9x9knUoVl33FitfU0Wv4yUEhnPTFFSJB3CqZXOtBzY4vSEZR+1ypa5x4Jp54J/+dI413Z0j5vqOORm1mbVnGB+WrMor5wVHSDaF8uYAnSAngca8e84KQa1FYoMmqJukfNc8evj3hvTE86+3yTJMi1+Rk8c9Te3Z1jB57v3P0VGRefeKy1UnrQwWKeB5fHrywQp+ZrwCtsZpiTHXct2RQPK83nZ17u6pn/lDPmNfc+w8xVfXMMO+cqzdaXObcc3+YX8k+LlgeuYFGIR+FQc+FzzqmI/iDxhoAok8v37a36WH+p+3EUNBA9LvPz20paHqixVVz31Zl+LzoQOk3IDbVBkWsEUNwjDyAt3iX6Yt/UpJeQgkO1AaFpxpehldTXtLlVO7YtMt6WWeyTmu5DUJws7y6XGvdpg9tEdy/KKu7E6i96aX0twhFX3AjfRRWG4UlNwSJTW6Qu32VEIZEIlSa5Vd4U1MSrTdUZuq3Vxo26w8LFUe+A+mZ25DgfIiHAwuKS39BSjsLiQ2/+0rQd1DghcFCZ9DOJHVPaJKuTanXd4ykiW2sPqF7RCW8NS8RuryS+KtjSlHLgB5rWE/jMyhkpG2DTHKrh6Gb3Axt8zCciztdCHYI1y5G5MfmeYp/jHM5EmwsecM5TNIv3SPrTl0huEoiahsi/wH6BvDV3KP6twAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"2016_Q1_Social-Sharing-Global-Popularity\"\n        title=\"2016_Q1_Social-Sharing-Global-Popularity\"\n        src=\"/static/f592b788f42ba34116f1947afb4e2b88/e5715/2016_Q1_Social-Sharing-Global-Popularity.png\"\n        srcset=\"/static/f592b788f42ba34116f1947afb4e2b88/a6d36/2016_Q1_Social-Sharing-Global-Popularity.png 650w,\n/static/f592b788f42ba34116f1947afb4e2b88/e5715/2016_Q1_Social-Sharing-Global-Popularity.png 768w,\n/static/f592b788f42ba34116f1947afb4e2b88/7510d/2016_Q1_Social-Sharing-Global-Popularity.png 2119w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>Some more critical insights provided by the analysis are:</p>\n<ul>\n<li>\n<ul>\n<li>In Q1 2016, females trumped males in the use of Social Login by 14%.</li>\n</ul>\n</li>\n<li>\n<ul>\n<li>Among mobile platforms too, iOS run devices lead the way pipping Android.</li>\n</ul>\n</li>\n<li>About 92% websites still prefer providing Facebook as one of the options for Social Login leading the favourites list since 2013.</li>\n</ul>\n<p><a href=\"https://www.loginradius.com/book-a-demo/\"><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 768px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 30.307692307692307%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAAAsSAAALEgHS3X78AAABdElEQVQY002RO0/CUBzFG6PtbZWHCAmRmBB5P8vDII9SSC0omog4oAEGjZMO6OKEuLjoJ2Fx0cSBwUQnXZxcHPwux38LJA7nNvfec8+5v1tOCCiwpbbhye2BxbYgBMtgIRVioDRRsARGXxZUzLlEHmehBaesQ4rrEMPViYf2DR9nDGKkChbVICVqsMt1WJI1sHCFwhUsUIFohJH49TxECvRUjhDW2mAbB5iP6hB8hUkhiRPN5KIZYJdrsEYrcCSpmQqMm6/m9ylUhSulY7N5ivROB3L9GOlGF3Ktbc4zuz341UPw/uIk0ESbBjoSGlYIx8BfzjSwVmyCEYEUUmCPa3Bnd+hwC75yC95S05SxbolU/iEbOCFCpDexEfIioTNCNd6Tp6IlMnNuGeeDe3z//OLx5RWj5zFGT2O8fXxh/P4Ja6w6vSEFCnTIlW2YiDzhzX7ATFKojDlvjpBPcDF4QPdyiG5/iE7/BmfXd+hd3VKpCoG8fzxWw2+c+yTpAAAAAElFTkSuQmCC'); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"book-a-demo-loginradius-banner\"\n        title=\"book-a-demo-loginradius-banner\"\n        src=\"/static/fcc4c4b5dc38cc4528f99d09480f4eb2/e5715/book-a-demo-loginradius.png\"\n        srcset=\"/static/fcc4c4b5dc38cc4528f99d09480f4eb2/a6d36/book-a-demo-loginradius.png 650w,\n/static/fcc4c4b5dc38cc4528f99d09480f4eb2/e5715/book-a-demo-loginradius.png 768w,\n/static/fcc4c4b5dc38cc4528f99d09480f4eb2/63ff0/book-a-demo-loginradius.png 2887w\"\n        sizes=\"(max-width: 768px) 100vw, 768px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></a></p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n</style>","frontmatter":{"date":"April 15, 2016","updated_date":null,"description":"From the beginning to the end of the customer-business relationship, customer engagement is the central aspect of individual user interactions.","title":"Customer Identity Preference Trends Q1 2016","tags":["customer identity management","ciam platform","cx"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":0.7751937984496124,"src":"/static/5fc5c5ffde6b586e913dd01591c4796e/e1953/customer-identity-preference-trends-q1-2016.png","srcSet":"/static/5fc5c5ffde6b586e913dd01591c4796e/69585/customer-identity-preference-trends-q1-2016.png 200w,\n/static/5fc5c5ffde6b586e913dd01591c4796e/e1953/customer-identity-preference-trends-q1-2016.png 250w","sizes":"(max-width: 250px) 100vw, 250px"}}},"author":{"id":"Rakesh Soni","github":"oyesoni","avatar":"rakesh-soni.jpg"}}}},{"node":{"excerpt":"I often come across people and clients who would like to build their custom login, registration, and lost password form in WordPress instead…","fields":{"slug":"/engineering/wordpress-custom-login-form-part-1/"},"html":"<p>I often come across people and clients who would like to build their custom login, registration, and lost password form in WordPress instead of using the default wp-login.php page. It's probably because it's too wordpress-y.</p>\n<p>In this tutorial, I will demonstrate how to build a custom login form using the default functionality that wordpress gives us.</p>\n<ul>\n<li><a href=\"#buildlogin\">Building a Custom Login Form</a></li>\n<li><a href=\"#loginresponse\">Handling the Login Form Response</a></li>\n</ul>\n<h2 id=\"building-a-wordpress-login-form-out-of-the-box\" style=\"position:relative;\"><a href=\"#building-a-wordpress-login-form-out-of-the-box\" aria-label=\"building a wordpress login form out of the box permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Building a WordPress Login Form (Out of the box)</h2>\n<p>This is what WordPress gives us out of the box.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 574px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 79.79094076655052%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAQCAIAAACZeshMAAAACXBIWXMAAAsTAAALEwEAmpwYAAABSUlEQVQoz42TsU7DMBCG+568QDfExM6MxMLEysTAwAOAhACpEogBVQUxhgoS3DRnOznHTuLyJyVQVU3aXydHOfvz+c7ngewWa2VS3bNgsNFLDXl6O9m/fPwUc61qz05wQoSA4yAcXoz2zh/O7t5spuHcCSaiVMmPKD65GR9ePV1PAuy1E6yUhpRSnOmY5FTM8yyF90+bYQRkZu99URRlWfpaC8hX3rc/mOqEjTEy5ShOYtLGldyY+bfKuV44xnlzZ2zBuVs1kzvJ8DvVDTOmpc4yY21ZrZkr/ZbIzloUxTAj7ao1yDWF6MsZBata1YArlgYQhYNtgbESIyOBZfCmyO+JORhNj18iMna129bhhUdiv8L1VM1tvSZmeB8cPX8lbNM+uFedx17dZfk2qG1JfATJGfW2J7pPCBGGoZiJ6LtWFIUYiTY+KvkDJA6JMgMgcv4AAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"wp-login\"\n        title=\"wp-login\"\n        src=\"/static/65a844891c904aa48a40be38b7735f76/86389/wp-login.png\"\n        srcset=\"/static/65a844891c904aa48a40be38b7735f76/86389/wp-login.png 574w\"\n        sizes=\"(max-width: 574px) 100vw, 574px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span><br>\nThere are quite a few different options available to make a custom login page. You can build a <a href=\"https://codex.wordpress.org/Shortcode_API\">shortcode</a> so that you could simply put [wp-login] or something you like on any page/post, make a page theme file and use that page to attach to a post/page, a widget could be a good solution too, or maybe you'd like to simply edit the existing form and add some pizzazz to it.</p>\n<p>I am going to show you all of this tutorial using the page-theme method because it is probably the easiest to implement for beginners. This will also give you an intro into page themes, if your not familiar with it.</p>\n<p>To start our theme, you will need to do the following:</p>\n<ol>\n<li>Install WordPress</li>\n<li>Navigate to your <em>wp-content/themes</em> folder and choose a theme to edit or install a new one</li>\n<li>create a file called <em>page-login.php</em> in the theme directory</li>\n<li>Next open that file with a text editor of your choosing and add the following at the top of the php file.</li>\n</ol>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"php\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;lt;?php</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">/*</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">Template Name: Login</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">get_header</span><span class=\"mtk1\">(); ?</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;lt;div id=</span><span class=\"mtk8\">&quot;primary&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk4\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;content-area&quot;</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;lt;div id=</span><span class=\"mtk8\">&quot;content&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk4\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;site-content&quot;</span><span class=\"mtk1\"> role=</span><span class=\"mtk8\">&quot;main&quot;</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;lt;/div</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt;</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;lt;!-- </span><span class=\"mtk3\">#content --&amp;amp;amp;gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;lt;/div</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt;</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;lt;!-- </span><span class=\"mtk3\">#primary --&amp;amp;amp;gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;lt;?php </span><span class=\"mtk11\">get_sidebar</span><span class=\"mtk1\">(); ?</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;lt;?php </span><span class=\"mtk11\">get_footer</span><span class=\"mtk1\">(); ?</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt;</span></span></code></pre>\n<p>To initialize this page template, make sure to activate the theme you've selected in \"Appearance/Themes\" in your admin dashboard and then navigate to a page or post. On the right hand side of your page/post editor you should now see a dropdown available for template under \"Page Attributes\". Change your template to \"Login\" or to the name that you specified in \"Template Name:\" and that will attach that page theme to this page/post.</p>\n<p>Now we're ready to start editing this page-login.php template file. So first open this file in your favorite editor and Let's get a login page started.</p>\n<p>To quickly show you how to get this login on the page Let's paste the following code between the div with id of content.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"php\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;lt;div id=</span><span class=\"mtk8\">&quot;primary&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk4\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;content-area&quot;</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;lt;div id=</span><span class=\"mtk8\">&quot;content&quot;</span><span class=\"mtk1\"> </span><span class=\"mtk4\">class</span><span class=\"mtk1\">=</span><span class=\"mtk8\">&quot;site-content&quot;</span><span class=\"mtk1\"> role=</span><span class=\"mtk8\">&quot;main&quot;</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;lt;?php </span><span class=\"mtk11\">wp_login_form</span><span class=\"mtk1\">(); ?</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;lt;/div</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt;</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;lt;!-- </span><span class=\"mtk3\">#content --&amp;amp;amp;gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;lt;/div</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt;</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;lt;!-- </span><span class=\"mtk3\">#primary --&amp;amp;amp;gt;</span></span></code></pre>\n<p>Look at what that small piece of code do</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 620px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 47.096774193548384%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAIAAAC9o5sfAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAZElEQVQoz8XRTQuAIAwGYP//H9WDuA+WCTlrF6lDZOSh9zAEeZibznuvqvunuBCCYVkEENac7Vx7RMTqALfWmDmlVEq5Yia2qzEmIns/WBC33u1ZnhgRYoxvwM3MUwv7A8/88wGsLxStC5PBOgAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"custom-login\"\n        title=\"custom-login\"\n        src=\"/static/48eca8e7849771947eb5cf7f664a0d27/2a195/custom-login.png\"\n        srcset=\"/static/48eca8e7849771947eb5cf7f664a0d27/2a195/custom-login.png 620w\"\n        sizes=\"(max-width: 620px) 100vw, 620px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span></p>\n<p>Now we need to set some arguments that we can provide to this form to customize it. Let's take a look at the documentation for <a href=\"https://developer.wordpress.org/reference/functions/wp_login_form/\">wp<em>login</em>form()</a></p>\n<p>In that document, it explains all the uses and arguments of wp<em>login</em>form(). Let's use those arguments section and see what happens. Paste the $args section shown in the wordpress doc right above our login form.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"php\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;lt;?php </span><span class=\"mtk12\">$args</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">array</span><span class=\"mtk1\">(</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk8\">&#39;echo&#39;</span><span class=\"mtk1\"> =</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt; </span><span class=\"mtk4\">true</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk8\">&#39;redirect&#39;</span><span class=\"mtk1\"> =</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt; ( </span><span class=\"mtk11\">is_ssl</span><span class=\"mtk1\">() ? </span><span class=\"mtk8\">&#39;https://&#39;</span><span class=\"mtk1\"> : </span><span class=\"mtk8\">&#39;http://&#39;</span><span class=\"mtk1\"> ) . </span><span class=\"mtk12\">$_SERVER</span><span class=\"mtk1\">[</span><span class=\"mtk8\">&#39;HTTP_HOST&#39;</span><span class=\"mtk1\">] . </span><span class=\"mtk12\">$_SERVER</span><span class=\"mtk1\">[</span><span class=\"mtk8\">&#39;REQUEST_URI&#39;</span><span class=\"mtk1\">],</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk8\">&#39;form_id&#39;</span><span class=\"mtk1\"> =</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt; </span><span class=\"mtk8\">&#39;loginform&#39;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk8\">&#39;label_username&#39;</span><span class=\"mtk1\"> =</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt; </span><span class=\"mtk11\">__</span><span class=\"mtk1\">( </span><span class=\"mtk8\">&#39;Username&#39;</span><span class=\"mtk1\"> ),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk8\">&#39;label_password&#39;</span><span class=\"mtk1\"> =</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt; </span><span class=\"mtk11\">__</span><span class=\"mtk1\">( </span><span class=\"mtk8\">&#39;Password&#39;</span><span class=\"mtk1\"> ),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk8\">&#39;label_remember&#39;</span><span class=\"mtk1\"> =</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt; </span><span class=\"mtk11\">__</span><span class=\"mtk1\">( </span><span class=\"mtk8\">&#39;Remember Me&#39;</span><span class=\"mtk1\"> ),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk8\">&#39;label_log_in&#39;</span><span class=\"mtk1\"> =</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt; </span><span class=\"mtk11\">__</span><span class=\"mtk1\">( </span><span class=\"mtk8\">&#39;Log In&#39;</span><span class=\"mtk1\"> ),</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk8\">&#39;id_username&#39;</span><span class=\"mtk1\"> =</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt; </span><span class=\"mtk8\">&#39;user_login&#39;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk8\">&#39;id_password&#39;</span><span class=\"mtk1\"> =</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt; </span><span class=\"mtk8\">&#39;user_pass&#39;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk8\">&#39;id_remember&#39;</span><span class=\"mtk1\"> =</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt; </span><span class=\"mtk8\">&#39;rememberme&#39;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk8\">&#39;id_submit&#39;</span><span class=\"mtk1\"> =</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt; </span><span class=\"mtk8\">&#39;wp-submit&#39;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk8\">&#39;remember&#39;</span><span class=\"mtk1\"> =</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt; </span><span class=\"mtk4\">true</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk8\">&#39;value_username&#39;</span><span class=\"mtk1\"> =</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt; </span><span class=\"mtk8\">&#39;&#39;</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk8\">&#39;value_remember&#39;</span><span class=\"mtk1\"> =</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt; </span><span class=\"mtk4\">false</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">); ?</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;lt;?php </span><span class=\"mtk11\">wp_login_form</span><span class=\"mtk1\">( </span><span class=\"mtk12\">$args</span><span class=\"mtk1\"> ); ?</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt;</span></span></code></pre>\n<p>It will look the same as the one we did earlier but, by customizing the arguments above, you can customize elements of the login form.</p>\n<h2 id=\"handling-the-login-form-response-custom\" style=\"position:relative;\"><a href=\"#handling-the-login-form-response-custom\" aria-label=\"handling the login form response custom permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Handling the login form response (Custom)</h2>\n<p>To handle the Login Form response we need to grab the $_POST parameters and login the user. You can create this as complex as you like, but I will demonstrate a simpler but effective method.</p>\n<p>For this action, we'll be using the <strong>after<em>setup</em>theme</strong> and <strong>wp_authenticate</strong>. I have added the following two functions within the functions.php file. The first function <strong>optional<em>email</em>address_login</strong> searches for a users email address based on their username, with this functionality you can log in using your email address or the username.</p>\n<p>The second function, <strong>login_user</strong>, handles the actual functionality of the login by receiving the $<em>POST parameters and passing them into the wp</em>signon method.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"php\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk3\">/**</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">* optional_email_address_login allows the user</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">* to log in with a email address as well as a username</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">* </span><span class=\"mtk4\">@param</span><span class=\"mtk3\"> </span><span class=\"mtk4\">string</span><span class=\"mtk3\"> &amp;amp;amp;amp;$username username or email</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">* </span><span class=\"mtk4\">@param</span><span class=\"mtk3\"> </span><span class=\"mtk4\">string</span><span class=\"mtk3\"> &amp;amp;amp;amp;$password password</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">optional_email_address_login</span><span class=\"mtk1\">( &amp;amp;amp;amp;</span><span class=\"mtk12\">$username</span><span class=\"mtk1\">, &amp;amp;amp;amp;</span><span class=\"mtk12\">$password</span><span class=\"mtk1\"> ) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">$user</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">get_user_by</span><span class=\"mtk1\">( </span><span class=\"mtk8\">&#39;email&#39;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">$username</span><span class=\"mtk1\"> );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">if</span><span class=\"mtk1\"> ( ! </span><span class=\"mtk11\">empty</span><span class=\"mtk1\">( </span><span class=\"mtk12\">$user</span><span class=\"mtk1\">-</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt;user_login ) )</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">{</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">$username</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">$user</span><span class=\"mtk1\">-</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt;user_login;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">// Allows the use of email logins</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">add_action</span><span class=\"mtk1\">( </span><span class=\"mtk8\">&#39;wp_authenticate&#39;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&#39;optional_email_address_login&#39;</span><span class=\"mtk1\">, </span><span class=\"mtk7\">1</span><span class=\"mtk1\">, </span><span class=\"mtk7\">2</span><span class=\"mtk1\"> );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">/**</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">* login_user handles the $_POST array and logs in users</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">*/</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">login_user</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">if</span><span class=\"mtk1\"> ( ! </span><span class=\"mtk11\">is_user_logged_in</span><span class=\"mtk1\">() ) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">$creds</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">array</span><span class=\"mtk1\">();</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">$creds</span><span class=\"mtk1\">[</span><span class=\"mtk8\">&#39;user_login&#39;</span><span class=\"mtk1\">] = </span><span class=\"mtk11\">isset</span><span class=\"mtk1\">( </span><span class=\"mtk12\">$_POST</span><span class=\"mtk1\">[</span><span class=\"mtk8\">&#39;log&#39;</span><span class=\"mtk1\">] ) ? </span><span class=\"mtk12\">$_POST</span><span class=\"mtk1\">[</span><span class=\"mtk8\">&#39;log&#39;</span><span class=\"mtk1\">] : </span><span class=\"mtk8\">&#39;&#39;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">$creds</span><span class=\"mtk1\">[</span><span class=\"mtk8\">&#39;user_password&#39;</span><span class=\"mtk1\">] = </span><span class=\"mtk11\">isset</span><span class=\"mtk1\">( </span><span class=\"mtk12\">$_POST</span><span class=\"mtk1\">[</span><span class=\"mtk8\">&#39;pwd&#39;</span><span class=\"mtk1\">] ) ? </span><span class=\"mtk12\">$_POST</span><span class=\"mtk1\">[</span><span class=\"mtk8\">&#39;pwd&#39;</span><span class=\"mtk1\">] : </span><span class=\"mtk8\">&#39;&#39;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">$creds</span><span class=\"mtk1\">[</span><span class=\"mtk8\">&#39;remember&#39;</span><span class=\"mtk1\">] = </span><span class=\"mtk11\">isset</span><span class=\"mtk1\">( </span><span class=\"mtk12\">$_POST</span><span class=\"mtk1\">[</span><span class=\"mtk8\">&#39;rememberme&#39;</span><span class=\"mtk1\">] ) ? </span><span class=\"mtk4\">true</span><span class=\"mtk1\"> : </span><span class=\"mtk4\">false</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">$user</span><span class=\"mtk1\"> = </span><span class=\"mtk11\">wp_signon</span><span class=\"mtk1\">( </span><span class=\"mtk12\">$creds</span><span class=\"mtk1\">, </span><span class=\"mtk4\">false</span><span class=\"mtk1\"> );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk15\">if</span><span class=\"mtk1\"> ( </span><span class=\"mtk11\">is_wp_error</span><span class=\"mtk1\">( </span><span class=\"mtk12\">$user</span><span class=\"mtk1\"> ) ) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">error_log</span><span class=\"mtk1\">( </span><span class=\"mtk12\">$user</span><span class=\"mtk1\">-</span><span class=\"mtk4\">&</span><span class=\"mtk1\">amp;amp;amp;gt;</span><span class=\"mtk11\">get_error_message</span><span class=\"mtk1\">() );</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">// Run login_user before headers and cookies are sent</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk11\">add_action</span><span class=\"mtk1\">( </span><span class=\"mtk8\">&#39;after_setup_theme&#39;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&#39;login_user&#39;</span><span class=\"mtk1\"> );</span></span></code></pre>\n<p>In this example I have used the default WordPress login form that you could customize and style to your desire. In the next blog, I will be demonstrating how to build a login form that is fully customized. We won’t be using the provided wordpress functions!</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n</style>","frontmatter":{"date":"March 01, 2016","updated_date":null,"description":null,"title":"Wordpress Custom Login Form Part 1","tags":["WordPress","Learning"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1,"src":"/static/400bee4b6d2f5f571912dff23f863421/6d161/wordpress-icon-150x1501-150x150.png","srcSet":"/static/400bee4b6d2f5f571912dff23f863421/6d161/wordpress-icon-150x1501-150x150.png 150w","sizes":"(max-width: 150px) 100vw, 150px"}}},"author":{"id":"Zoie Carnegie","github":null,"avatar":null}}}},{"node":{"excerpt":"1. Secure your server Many known attacks are possible only once physically accessing a machine. For this reason, it is best to have the…","fields":{"slug":"/engineering/is-your-database-secured-think-again/"},"html":"<p><strong>1. Secure your server</strong></p>\n<p>Many known attacks are possible only once physically accessing a machine. For this reason, it is best to have the application server and the database server on different machines. If this is not possible, greater care must be taken, Otherwise, by executing remote commands via an application server, an attacker may be able to harm your database even without permissions. For this reason, any service running on the same machine as the database should be granted the lowest possible permission that still allows the service to operate.</p>\n<p><span\n      class=\"gatsby-resp-image-wrapper\"\n      style=\"position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 494px; \"\n    >\n      <span\n    class=\"gatsby-resp-image-background-image\"\n    style=\"padding-bottom: 38.8663967611336%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAAsTAAALEwEAmpwYAAABPUlEQVQY031Q2U7DQAzc//8GfgOEBELiGXGofQlpQumRZnNtstnLewaXvlEJa2RZs56x12S5Chdi0chdr8pGHpnediqnIqdyP+h6grJV+MSNx07SzxrxR29cQFgf0ciHBC4acGCddw7AGrDBoziRshHbTi7/hzVnODhnD0vAQicjSXYc8mqYpEGnGBNm4/xq1z+uq009+YBcWqyiHJ6z5v2bHXrR4tJxSXIk+YHme9qOAru8DzjmqxW3b/v7VbUqjlxCQrHXn/V885TdvW4f1tVHcaJMLnomBeUlnZX1lwUVhAPTGyrwNsdB9sK6kBanqwleyj47TWVvdoNupU1yIsJ4CeeB6Vc8KXcaTcMNyjph2xkAVwQ1s5H1DDEzNnQDH3lSnFxfh2vHpEWgEd78QuIPI6NpaiOrEUkwJH8ANN/IbQHv70QAAAAASUVORK5CYII='); background-size: cover; display: block;\"\n  ></span>\n  <img\n        class=\"gatsby-resp-image-image\"\n        alt=\"server-network-structure\"\n        title=\"server-network-structure\"\n        src=\"/static/db8fbab272d550b5b8073c8972f51a65/d72d4/server-network-structure.png\"\n        srcset=\"/static/db8fbab272d550b5b8073c8972f51a65/d72d4/server-network-structure.png 494w\"\n        sizes=\"(max-width: 494px) 100vw, 494px\"\n        style=\"width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;\"\n        loading=\"lazy\"\n      />\n    </span><br>\nDo not forget to install the whole security package: Antivirus and Anti-spam, Firewall, and all of the security packages recommended by your operating system's vendor. Also, do not forget to spend 10 minutes thinking of your server's physical location - in the wrong location, your server can be stolen, flooded, harmed by wild animals or vagrants.</p>\n<p><strong>2. Localhost Security or Disable or restrict remote access</strong></p>\n<p>Consider whether MySQL will be retrieved from the system or directly accessed from its own server. On the off chance that remote access is utilized, guarantee that just characterized hosts can get to the server. This is commonly done through TCP wrappers, IP tables, or some other firewall programming or hardware accessibility tools.<br>\nTo confine MySQL from opening a network socket, the accompanying parameter ought to be included in the [mysqld] area of my.cnf or my.ini:</p>\n<p>skip-networking</p>\n<p>The document is situated in the <em>\"C:\\Program Files\\MySQL\\MySQL Server 5.1\"</em> catalog on the Windows operating system or <em>\"/etc/my.cnf\"</em> or <em>\"/etc/mysql/my.cnf\"</em> on Linux.<br>\nThis line cripples the start of systems administration in the middle of MySQL startup. It would be ideal if you bear in mind that a local connection can be used set up a connection to the MySQL server.</p>\n<p>Another possible solution is to force MySQL to listen only to the localhost by adding the following line in the <em>[mysqld]</em> section of <em>my.cnf</em>bind-address=127.0.0.1<br>\nYou may not be willing to incapacitate system access to your database server if clients in your organization interface with the server from their machines or the web server introduced on an alternate machine. In that case, the following restrictive grant syntax should be considered:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">mysql&gt; GRANT SELECT, INSERT ON mydb.\\* TO &#39;someuser&#39;@&#39;somehost&#39;;  </span></code></pre>\n<p><strong>3. Disable the use of LOCAL INFILE</strong></p>\n<p>The next change is to disable the use of the <em>\"LOAD DATA LOCAL INFILE\"</em> command, which will help to keep unapproved perusing from neighborhood records. This is particularly vital when new SQL Injection vulnerabilities in PHP applications are found.<br>\nIn addition, in certain cases, the <em>\"LOCAL INFILE\"</em> command can be used to gain access to other files on the operating system, for instance <em>\"/etc/passwd\"</em>, using the following command:  </p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">mysql&gt; LOAD DATA LOCAL INFILE &#39;/etc/passwd&#39; INTO TABLE table1</span></code></pre>\n<p>Or even significantly less difficult:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">mysql&gt; SELECT load\\_file(&quot;/etc/passwd&quot;)</span></code></pre>\n<p>To disable the usage of the <em>\"LOCAL INFILE\"</em> command, the following parameter should be added in the <em>[mysqld]</em> section of the MySQL configuration file.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">set-variable=local-infile=0</span></code></pre>\n<p><strong>4. Change root username and password, keep them strong.</strong></p>\n<p>The default administrator username on the MySQL server is <strong>\"root\"</strong>. Hackers often attempt to gain access to its permissions. To make this task harder, rename <strong>\"root\"</strong> to something else and provide it with a long, complex alphanumeric password.</p>\n<p>To rename the administrator’s username, use the rename command in the MySQL console:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">mysql&gt; RENAME USER root TO new\\_user;</span></code></pre>\n<p>The MySQL <em>\"RENAME USER\"</em> command first appeared in MySQL version 5.0.2. If you use an older version of MySQL, you can use other commands to rename a user:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">mysql&gt; use mysql;</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">mysql&gt; update user set user=&quot;new\\_user&quot; where user=&quot;root&quot;;</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">mysql&gt; flush privileges;</span></code></pre>\n<p>To change a user’s password, use the following command-line command:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">mysql&gt; SET PASSWORD FOR &#39;username&#39;@&#39;%hostname&#39; = PASSWORD(&#39;newpass&#39;);</span></code></pre>\n<p>It is also possible to change the password using the <em>\"mysqladmin\"</em> utility:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"7\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">shell&gt; mysqladmin -u username -p password newpass</span></code></pre>\n<p><strong>5. Remove the \"Test\" database</strong></p>\n<p>MySQL comes with a \"test\" database intended as a test space. It can be accessed by the anonymous user, and is therefore used by numerous attacks.<br>\nTo remove this database, use the drop command as follows:  </p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"8\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">mysql&gt; drop database test;  </span></code></pre>\n<p>Or use the <em>\"mysqladmin\"</em> command:  </p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"9\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">shell&gt; mysqladmin -u username -p drop test  </span></code></pre>\n<p><strong>6. Remove Anonymous and outdated accounts</strong></p>\n<p>The MySQL database comes with some anonymous users with blank passwords. As a result, anyone can connect to the database to check whether this is the case, do the following:  </p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"10\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">mysql&gt; select \\* from mysql.user where user=&quot;&quot;;  </span></code></pre>\n<p>In a secure system, no lines should be echoed back. Another way to do the same:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"11\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">mysql&gt; SHOW GRANTS FOR &#39;&#39;@&#39;localhost&#39;;</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">mysql&gt; SHOW GRANTS FOR &#39;&#39;@&#39;myhost&#39;;</span></code></pre>\n<p>If the grants exist, then anybody can access the database and at least use the default database<em>\"test\"</em>. Check this with:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"12\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">shell&gt; mysql -u blablabla</span></code></pre>\n<p>To remove the account, execute the following command:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"13\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">mysql&gt; DROP USER &quot;&quot;;</span></code></pre>\n<p>The MySQL <em>\"DROP USER\"</em> command is supported starting with MySQL version 5.0. If you use an older version of MySQL, you can remove the account as follows:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"14\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">mysql&gt; use mysql;</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">mysql&gt; DELETE FROM user WHERE user=&quot;&quot;;</span>\n<span class=\"grvsc-line\"></span>\n<span class=\"grvsc-line\">mysql&gt; flush privileges;  </span></code></pre>\n<p><strong>7. Increase security with Role Based Access Control</strong></p>\n<p>A very common database security recommendation is to lower the permissions given to various parties. MySQL is no different. Typically, when developers work, they use the system's maximum permission and give less consideration to permission principles than we might expect. This practice can expose the database to significant risk.<br>\n* Any new MySQL 5.x installation already installed using the correct security measures.<br>\nTo protect your database, make sure that the file directory in which the MySQL database is actually stored is owned by the user \"mysql\" and the group \"mysql\".</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"15\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">shell&gt;ls -l /var/lib/mysql</span></code></pre>\n<p>In addition, ensure that only the user \"mysql\" and \"root\" have access to the directory <code>/var/lib/mysql</code>.<br>\nThe mysql binaries, which reside under the /usr/bin/ directory, should be owned by \"root\" or the specific system \"mysql\" user. Other users should not have write access to these files.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"16\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">shell&gt;ls -l /usr/bin/my\\*  </span></code></pre>\n<p><strong>8. Keep a check on database privileges</strong></p>\n<p>Operating system permissions were fixed in the preceding section. Now let’s talk about database permissions. In most cases, there is an administrator user (the renamed \"root\") and one or more actual users who coexist in the database. Usually, the \"root\" has nothing to do with the data in the database; instead, it is used to maintain the server and its tables, to give and revoke permissions, etc.<br>\nOn the other hand, some user ids are used to access the data, such as the user id assigned to the web server to execute \"select\\update\\insert\\delete\" queries and to execute stored procedures. In most cases, no other users are necessary; however, only you, as a system administrator can really know your application’s needs.</p>\n<p>Only administrator accounts needs to be granted the SUPER / PROCESS /FILE privileges and access to the mysql database. Usually, it is a good idea to lower the administrator’s permissions for accessing the data.</p>\n<p>Review the privileges of the rest of the users and ensure that these are set appropriately. This can be done using the following steps.  </p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"17\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">mysql&gt; use mysql;  </span></code></pre>\n<p>[Identify users]  </p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"18\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">mysql&gt; select \\* from users;  </span></code></pre>\n<p>[List grants of all users]  </p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"19\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">mysql&gt; show grants for ‘root’@’localhost’;</span></code></pre>\n<p>The above statement has to be executed for each user ! Note that only users who really need root privileges should be granted them.</p>\n<p>Another interesting privilege is \"SHOW DATABASES\". By default, the command can be used by everyone having access to the MySQL prompt. They can use it to gather information (e.g., getting database names) before attacking the database by, for instance, stealing the data. To prevent this, it is recommended that you follow the procedures described below.</p>\n<ul>\n<li>Add \" --skip-show-database\" to the startup script of MySQL or add it to the MySQL configuration file</li>\n<li>Grant the SHOW DATABASES privilege only to the users you want to use this command</li>\n</ul>\n<p>To disable the usage of the \"SHOW DATABASES\" command, the following parameter should be added in the [mysqld] section of the <code>/etc/my.cnf</code>:</p>\n<p>[mysqld]</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"20\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">skip-show-database  </span></code></pre>\n<p><strong>9. Enable Logging</strong></p>\n<p>If your database server does not execute many queries, it is recommended that you enable transaction logging, by adding the following line to [mysqld] section of the <code>/etc/my.cnf</code> file:</p>\n<p>[mysqld]</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"21\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">log =/var/log/mylogfile  </span></code></pre>\n<p>This is not recommended for heavy production MySQL servers because it causes high overhead on the server.<br>\nIn addition, verify that only the \"root\" and \"mysql\" ids have access to these logfiles (at least write access).</p>\n<p><strong>Error log</strong>Ensure only \"root\" and \"mysql\" have access to the log file \"hostname.err\". The file is stored in the mysql data directory. This file contains very sensitive information such as passwords, addresses, table names, stored procedure names and code parts. It can be used for information gathering, and in some cases, can provide the attacker with the information needed to exploit the database, the machine on which the database is installed, or the data inside it.</p>\n<p><strong>MySQL log</strong>Ensure only \"root\" and \"mysql\" have access to the logfile \"logfile XY\". The file is stored in the mysql data directory.</p>\n<p><strong>10. Change the root directory</strong> </p>\n<p>A chroot on UNIX {operating system} operating systems is an operation that changes the apparent disk root directory for the present running method and its children. A program that's re-rooted to a different directory cannot access or name files outside that directory, and therefore the directory is named a \"chroot jail\" or (less commonly) a \"chroot prison\".</p>\n<p>By using the chroot environment, the write access of the mySQL processes (and child processes) can be limited, increasing the security of the server.</p>\n<p>Ensure that a dedicated directory exists for the chrooted environment. This should be something like: <code>/chroot/mysql</code> In addition, to make the use of the database administrative tools convenient, the following parameter should be changed in the [client] section of MySQL configuration file:</p>\n<p>[client]</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"22\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">socket = /chroot/mysql/tmp/mysql.sock</span></code></pre>\n<p>Thanks to that line of code, there will be no need to supply the mysql, mysqladmin, mysqldump etc. commands with the <code>--socket=/chroot/mysql/tmp/mysql.sock</code> parameter every time these tools are run.</p>\n<p><strong>11. Delete old logs regularly</strong></p>\n<p>During the installation procedures, there's plenty of sensitive data which will assist unwelcome users to assault a database. This data is kept within the server’s history and might be terribly useful if one thing goes wrong during the installation. By analyzing the history files, administrators can figure out what has gone wrong and probably fix things up. However, these files are not needed after installation is complete.<br>\nWe should remove the content of the MySQL history file (~/.mysql_history), wherever all dead SQL commands are kept (especially passwords, that are kept as plain text):</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"\" data-index=\"23\"><code class=\"grvsc-code\"><span class=\"grvsc-line\">cat /dev/null &gt; ~/.mysql\\_history</span></code></pre>\n<p>In conclusion,we should emphasize on database security. However it should be the first thing for any individual or a company.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n</style>","frontmatter":{"date":"February 23, 2016","updated_date":null,"description":null,"title":"Is Your Database Secured? Think Again","tags":["Database","Security"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1,"src":"/static/6a50b3ff2cea92449f2f6ab9856c8a0a/630fb/database_secure-300x300.png","srcSet":"/static/6a50b3ff2cea92449f2f6ab9856c8a0a/69585/database_secure-300x300.png 200w,\n/static/6a50b3ff2cea92449f2f6ab9856c8a0a/630fb/database_secure-300x300.png 300w","sizes":"(max-width: 300px) 100vw, 300px"}}},"author":{"id":"Kunal","github":"SuperKunal","avatar":null}}}},{"node":{"excerpt":"Manipulating collections like arrays and objects can be a hassle with vanilla JS. Thankfully there are libraries like Underscore which offer…","fields":{"slug":"/engineering/be-more-manipulative-with-underscore-js/"},"html":"<p>Manipulating collections like arrays and objects can be a hassle with vanilla JS. Thankfully there are libraries like Underscore which offer some extremely useful low level utility functions.</p>\n<p>Underscore JS provides much of the array/collection/object manipulating functionality similar to what you may have seen in other languages such as Ruby. As for calling the methods if you're familiar with JQuery, Underscore is identical except instead of \"$\" we use the library's namesake \"_\" to access the methods.</p>\n<p>Underscore has over 100 functions that can be used on collections, arrays, objects and functions (you read that right, function functions). I'm going to be discussing a few of the functions that work on collections, but definitely check out what else <a href=\"http://underscorejs.org/\">Underscore has to offer</a>.</p>\n<p>Once you know how to re-create the same output with Underscore syntax, you'll never want to go back to plain old JS and using nested for loops. One of the most helpful tools Underscore provides for accomplishing this is...</p>\n<h2 id=\"_each\" style=\"position:relative;\"><a href=\"#_each\" aria-label=\"_each permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>_.each</h2>\n<p>The _each method does exactly what it sounds like. It works on collections (arrays or objects), and will iterate over each element in the collection invoking the function you specified with 3 arguments (value, index, list) with index being replaced by key if used on an object. It's also worth noting _.each returns the list if you want chain some more manipulation after calling _.each.</p>\n<p>Here's a quick example showing how it can be used and what's available to you when you call it.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"javascript\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">someArray</span><span class=\"mtk1\"> = [</span><span class=\"mtk8\">&quot;a&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;b&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;c&quot;</span><span class=\"mtk1\">];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">_</span><span class=\"mtk1\">.</span><span class=\"mtk11\">each</span><span class=\"mtk1\">(</span><span class=\"mtk12\">someArray</span><span class=\"mtk1\">, </span><span class=\"mtk4\">function</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">element</span><span class=\"mtk1\">, </span><span class=\"mtk12\">index</span><span class=\"mtk1\">, </span><span class=\"mtk12\">list</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;value: &quot;</span><span class=\"mtk1\"> + </span><span class=\"mtk12\">element</span><span class=\"mtk1\"> + </span><span class=\"mtk8\">&quot; index: &quot;</span><span class=\"mtk1\"> + </span><span class=\"mtk12\">index</span><span class=\"mtk1\"> + </span><span class=\"mtk8\">&quot; list: &quot;</span><span class=\"mtk1\"> + </span><span class=\"mtk12\">list</span><span class=\"mtk1\">)</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">// outputs</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">value: </span><span class=\"mtk12\">a</span><span class=\"mtk1\"> index: </span><span class=\"mtk7\">0</span><span class=\"mtk1\"> list: </span><span class=\"mtk12\">a</span><span class=\"mtk1\">,</span><span class=\"mtk12\">b</span><span class=\"mtk1\">,</span><span class=\"mtk12\">c</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">value: </span><span class=\"mtk12\">b</span><span class=\"mtk1\"> index: </span><span class=\"mtk7\">1</span><span class=\"mtk1\"> list: </span><span class=\"mtk12\">a</span><span class=\"mtk1\">,</span><span class=\"mtk12\">b</span><span class=\"mtk1\">,</span><span class=\"mtk12\">c</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">value: </span><span class=\"mtk12\">c</span><span class=\"mtk1\"> index: </span><span class=\"mtk7\">2</span><span class=\"mtk1\"> list: </span><span class=\"mtk12\">a</span><span class=\"mtk1\">,</span><span class=\"mtk12\">b</span><span class=\"mtk1\">,</span><span class=\"mtk12\">c</span></span></code></pre>\n<p>With that out of the way, let's think about what this means in terms of cleaning up our code. To do the above normally we would write a little for loop like this.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"javascript\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk15\">for</span><span class=\"mtk1\"> ( </span><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">i</span><span class=\"mtk1\"> = </span><span class=\"mtk7\">0</span><span class=\"mtk1\">; </span><span class=\"mtk12\">i</span><span class=\"mtk1\"> &</span><span class=\"mtk12\">lt</span><span class=\"mtk1\">; </span><span class=\"mtk12\">someArray</span><span class=\"mtk1\">.</span><span class=\"mtk12\">length</span><span class=\"mtk1\">; </span><span class=\"mtk12\">i</span><span class=\"mtk1\">++) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;value: &quot;</span><span class=\"mtk1\"> + </span><span class=\"mtk12\">someArray</span><span class=\"mtk1\">[</span><span class=\"mtk12\">i</span><span class=\"mtk1\">] + </span><span class=\"mtk8\">&quot; index: &quot;</span><span class=\"mtk1\"> + </span><span class=\"mtk12\">i</span><span class=\"mtk1\"> + </span><span class=\"mtk8\">&quot; list: &quot;</span><span class=\"mtk1\"> + </span><span class=\"mtk12\">someArray</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span></code></pre>\n<p>Admittedly these two aren't all that different, but let's imagine we have a function defined elsewhere that will deal with handling the arguments passed in on each iteration. We can replace that same functionality with a significantly less verbose solution.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"javascript\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">_</span><span class=\"mtk1\">.</span><span class=\"mtk11\">each</span><span class=\"mtk1\">(</span><span class=\"mtk12\">someArray</span><span class=\"mtk1\">, </span><span class=\"mtk12\">doStuff</span><span class=\"mtk1\">);</span></span></code></pre>\n<p>To quote Antoine de Saint Exupéry: \"It seems that perfection is attained not when there is nothing more to add, but when there is nothing more to remove.\" While it may not be perfection, there are certainly arguments to be made about performance, I think you would be hard pressed to find anything further simplify this code.</p>\n<h2 id=\"_map\" style=\"position:relative;\"><a href=\"#_map\" aria-label=\"_map permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>_.map</h2>\n<p>While _.each will return the original list you input, _.map will allow you to manipulate or otherwise transform the input as you please and then returns the new array. Map needs a minimum of 2 arguments, first the collection and then the function to be executed on each iteratee and also accepts a third argument which dictates the context for the iterating function.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"javascript\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">numbersObject</span><span class=\"mtk1\"> = {</span><span class=\"mtk7\">1</span><span class=\"mtk12\">:</span><span class=\"mtk7\">1</span><span class=\"mtk1\">, </span><span class=\"mtk7\">2</span><span class=\"mtk12\">:</span><span class=\"mtk7\">4</span><span class=\"mtk1\">, </span><span class=\"mtk7\">3</span><span class=\"mtk12\">:</span><span class=\"mtk7\">9</span><span class=\"mtk1\">};</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">productArray</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">_</span><span class=\"mtk1\">.</span><span class=\"mtk11\">map</span><span class=\"mtk1\">(</span><span class=\"mtk12\">numbersObject</span><span class=\"mtk1\">, </span><span class=\"mtk4\">function</span><span class=\"mtk1\">(</span><span class=\"mtk12\">value</span><span class=\"mtk1\">, </span><span class=\"mtk12\">key</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk12\">value</span><span class=\"mtk1\"> * </span><span class=\"mtk12\">key</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">//proudctArray is now</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">[</span><span class=\"mtk7\">1</span><span class=\"mtk1\">, </span><span class=\"mtk7\">8</span><span class=\"mtk1\">, </span><span class=\"mtk7\">27</span><span class=\"mtk1\">]</span></span></code></pre>\n<p>Before you go writing some functions to pass as an argument to _.map be sure to take a peek at the other methods available in Underscore. Map is a little bit like having the Lego blocks to build whatever you want, but if you already have a pre-packaged Batcave available, it might not be the best use of your time building it from scratch.</p>\n<h2 id=\"_pluck\" style=\"position:relative;\"><a href=\"#_pluck\" aria-label=\"_pluck permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>_.pluck</h2>\n<p>To illustrate my childhood toy analogy let's talk about _.pluck. Pluck is basically just a refined version of _.map made for a specific use case. That's not to say there aren't ways of combining the two to achieve something a little more complex, but if standard _.pluck behaviour is all you're after then don't go re-inventing the wheel.</p>\n<p>Often with data objects we're interested in the values of a specific key, for example let's say we have an array of movies.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"javascript\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">movies</span><span class=\"mtk1\"> = [</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    {</span><span class=\"mtk12\">title:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Dracula&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">genre:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Horror&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">star:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Nosferatu&quot;</span><span class=\"mtk1\">},</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    {</span><span class=\"mtk12\">title:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Cast Away&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">genre:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Drama&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">star:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Wilson&quot;</span><span class=\"mtk1\">},</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    {</span><span class=\"mtk12\">title:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Airplane&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">genre:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Comedy&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">star:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Leslie Nielsen&quot;</span><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">];</span></span></code></pre>\n<p>Now we want to just have an array of the titles of these movies.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"javascript\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">titlesArray</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">_</span><span class=\"mtk1\">.</span><span class=\"mtk11\">pluck</span><span class=\"mtk1\">(</span><span class=\"mtk12\">movies</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&#39;title&#39;</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">//titlesArray is now</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">[</span><span class=\"mtk8\">&quot;Dracula&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;Cast Away&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;Airplane&quot;</span><span class=\"mtk1\">]</span></span></code></pre>\n<p>Not much else to say about it, it works on collections and is extremely handy for a very common task.</p>\n<h2 id=\"_filter\" style=\"position:relative;\"><a href=\"#_filter\" aria-label=\"_filter permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>_.filter</h2>\n<p>Another example of a more refined _.map function that comes in handy often enough. Aptly named this method will return an array of only the things that make it through your test.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"javascript\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">numbers</span><span class=\"mtk1\"> = [</span><span class=\"mtk7\">1</span><span class=\"mtk1\">,</span><span class=\"mtk7\">33</span><span class=\"mtk1\">,</span><span class=\"mtk7\">6</span><span class=\"mtk1\">,</span><span class=\"mtk7\">24</span><span class=\"mtk1\">,</span><span class=\"mtk7\">8</span><span class=\"mtk1\">,</span><span class=\"mtk7\">21</span><span class=\"mtk1\">,</span><span class=\"mtk7\">11</span><span class=\"mtk1\">,</span><span class=\"mtk7\">22</span><span class=\"mtk1\">];</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">var</span><span class=\"mtk1\"> </span><span class=\"mtk12\">lessThanTen</span><span class=\"mtk1\"> = </span><span class=\"mtk12\">_</span><span class=\"mtk1\">.</span><span class=\"mtk11\">filter</span><span class=\"mtk1\">(</span><span class=\"mtk12\">numbers</span><span class=\"mtk1\">, </span><span class=\"mtk4\">function</span><span class=\"mtk1\">(</span><span class=\"mtk12\">number</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">return</span><span class=\"mtk1\"> </span><span class=\"mtk12\">number</span><span class=\"mtk1\"> &</span><span class=\"mtk12\">lt</span><span class=\"mtk1\">; </span><span class=\"mtk7\">10</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">});</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\"> </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk3\">//lessThanTen is now</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">[</span><span class=\"mtk7\">1</span><span class=\"mtk1\">, </span><span class=\"mtk7\">6</span><span class=\"mtk1\">, </span><span class=\"mtk7\">8</span><span class=\"mtk1\">]</span></span></code></pre>\n<p>Works on collections and kitchen sink faucets.</p>\n<h2 id=\"_conclusion\" style=\"position:relative;\"><a href=\"#_conclusion\" aria-label=\"_conclusion permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>_.conclusion</h2>\n<p>Just kidding there's no _.conclusion method.</p>\n<p>I hope by now that you get the idea that if what you need to do isn't already a method, Underscore's _.map is a powerful tool for accomplishing whatever obscure collection manipulation your heart desires.</p>\n<p>So get out there, take a look through Underscore JS and start writing less obfuscated (nested) for loops with the help of _.each.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n  .dark-default-dark .mtk3 { color: #6A9955; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n</style>","frontmatter":{"date":"February 16, 2016","updated_date":null,"description":null,"title":"Be More Manipulative with Underscore JS","tags":["JavaScript","UnderscoreJs"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.7699115044247788,"src":"/static/11ed52d59476d63d8b5a6688fb02bdb9/ee604/underscore.png","srcSet":"/static/11ed52d59476d63d8b5a6688fb02bdb9/69585/underscore.png 200w,\n/static/11ed52d59476d63d8b5a6688fb02bdb9/497c6/underscore.png 400w,\n/static/11ed52d59476d63d8b5a6688fb02bdb9/ee604/underscore.png 800w,\n/static/11ed52d59476d63d8b5a6688fb02bdb9/f3583/underscore.png 1200w,\n/static/11ed52d59476d63d8b5a6688fb02bdb9/e4d72/underscore.png 1280w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Zakary Hughes","github":null,"avatar":null}}}},{"node":{"excerpt":"LinkedIn has recently revamped their API systems and added many new restrictions. We will go through some examples on how you can utilize…","fields":{"slug":"/engineering/extended-linkedin-api-usage/"},"html":"<p>LinkedIn has recently revamped their API systems and added many new restrictions. We will go through some examples on how you can utilize the LinkedIn Javascript API in order to setup some useful features that comply with LinkedIn's new terms and conditions and use cases.</p>\n<h2 id=\"getting-your-site-ready\" style=\"position:relative;\"><a href=\"#getting-your-site-ready\" aria-label=\"getting your site ready permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Getting Your Site Ready</h2>\n<p>The first step will be setting up your login button which will prompt the user to authenticate with their LinkedIn credentials. We have provided a guide to getting a basic login button setup <a href=\"/integrate-linkedin-social-login-website/\">here</a>. The linked guide will get you as far as setting up a button that allows your users to login with LinkedIn and display a personalized welcome message. Below we will go over extending this functionality to allow you to handle more complex features for your users after logging in.</p>\n<h2 id=\"event-handling\" style=\"position:relative;\"><a href=\"#event-handling\" aria-label=\"event handling permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Event Handling</h2>\n<p>You can control and initiate specific behavior after a user logs in. You can assign these event handlers by first setting the function that will be used to initialize the events. This will trigger the event designation after the LinkedIn scripts have been loaded on your page. Update the LinkedIn initialization script:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!--</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">api_key: </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">authorize: </span><span class=\"mtk4\">true</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">onLoad: </span><span class=\"mtk12\">onLinkedInLoad</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">--&gt;</span></span></code></pre>\n<p>This will trigger the onLinkedInLoad function after the Linkedin scripts have been loaded.</p>\n<p>You can now assign some LinkedIn Event handlers in this function to control the behavior that will occur for different LinkedIn user actions. Let's begin by assigning the behavior that occurs after a user logs in.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!--</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">onLinkedInLoad</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">IN</span><span class=\"mtk1\">.</span><span class=\"mtk12\">Event</span><span class=\"mtk1\">.</span><span class=\"mtk11\">on</span><span class=\"mtk1\">(</span><span class=\"mtk12\">IN</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;auth&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">getProfileData</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">--&gt;</span></span></code></pre>\n<p>The above event will trigger when a user authorizes and will call the getProfileData function. We can add another event assignment for the user logging out.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!--</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">onLinkedInLoad</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">IN</span><span class=\"mtk1\">.</span><span class=\"mtk12\">Event</span><span class=\"mtk1\">.</span><span class=\"mtk11\">on</span><span class=\"mtk1\">(</span><span class=\"mtk12\">IN</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;auth&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">getProfileData</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">IN</span><span class=\"mtk1\">.</span><span class=\"mtk12\">Event</span><span class=\"mtk1\">.</span><span class=\"mtk11\">on</span><span class=\"mtk1\">(</span><span class=\"mtk12\">IN</span><span class=\"mtk1\">, </span><span class=\"mtk8\">&quot;logout&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">sendGoodByeMessage</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">--&gt;</span></span></code></pre>\n<p>The above logout event will trigger the sendGoodByeMessage when the user logs out. Now that we have the basic event handling in place we can handle the specific behavior for users logging in.</p>\n<h2 id=\"data-retrieval-and-api-access\" style=\"position:relative;\"><a href=\"#data-retrieval-and-api-access\" aria-label=\"data retrieval and api access permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Data Retrieval and API access</h2>\n<p>Once a user has logged in and triggered the getProfileData event we can pull in their user profile using the LinkedIn Raw data API handlers, these allow you to access any of LinkedIn's API endpoints and get data back. We will begin with a quick check to make sure the user is still authorized and then call the Raw API to pull in the people endpoint for the current user:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!--</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">getProfileData</span><span class=\"mtk1\">() {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk15\">if</span><span class=\"mtk1\">(</span><span class=\"mtk12\">IN</span><span class=\"mtk1\">.</span><span class=\"mtk12\">User</span><span class=\"mtk1\">.</span><span class=\"mtk11\">isAuthorized</span><span class=\"mtk1\">())</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">IN</span><span class=\"mtk1\">.</span><span class=\"mtk12\">API</span><span class=\"mtk1\">.</span><span class=\"mtk11\">Raw</span><span class=\"mtk1\">(</span><span class=\"mtk8\">&quot;/people/~&quot;</span><span class=\"mtk1\">).</span><span class=\"mtk11\">result</span><span class=\"mtk1\">(</span><span class=\"mtk12\">onSuccess</span><span class=\"mtk1\">).</span><span class=\"mtk11\">error</span><span class=\"mtk1\">(</span><span class=\"mtk12\">onError</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">--&gt;</span></span></code></pre>\n<p>If the data is successfully returned it will call the onSuccess function and if not it will call onError.</p>\n<p>These functions will both include a JSON formatted response that can be used to display their profile data or log a message:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!--</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">onSuccess</span><span class=\"mtk1\">(</span><span class=\"mtk12\">data</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk12\">data</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk4\">function</span><span class=\"mtk1\"> </span><span class=\"mtk11\">onError</span><span class=\"mtk1\">(</span><span class=\"mtk12\">error</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk10\">console</span><span class=\"mtk1\">.</span><span class=\"mtk11\">log</span><span class=\"mtk1\">(</span><span class=\"mtk12\">error</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">--&gt;</span></span></code></pre>\n<p>You can test the response formats for most of the LinkedIn APIs on <a href=\"https://apigee.com/console/linkedin\">LinkedIns API console</a> You can access any of the API endpoints after successful login via the raw API handler and retrieve data per your requirements.</p>\n<h2 id=\"user-management\" style=\"position:relative;\"><a href=\"#user-management\" aria-label=\"user management permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>User Management</h2>\n<p>Before making any API requests you should verify that your user has a current active session. User sessions are valid for 30 minutes by default. These sessions can be extended using the following call:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!--</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">IN</span><span class=\"mtk1\">.</span><span class=\"mtk12\">User</span><span class=\"mtk1\">.</span><span class=\"mtk11\">refresh</span><span class=\"mtk1\">()</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">--&gt;</span></span></code></pre>\n<p>The above call can be used to refresh the expiration time for the user but repeated calls may cause your app to be blocked so this should be used sparingly.</p>\n<p>You can provide the ability for your users to logout by setting up a button or link that will trigger the following function call:</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!--</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk12\">IN</span><span class=\"mtk1\">.</span><span class=\"mtk12\">User</span><span class=\"mtk1\">.</span><span class=\"mtk11\">logout</span><span class=\"mtk1\">(</span><span class=\"mtk12\">sendGoodByeMessage</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">--&gt;</span></span></code></pre>\n<p>This will trigger the same function that was assigned to the logout event.</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk15 { color: #C586C0; }\n  .dark-default-dark .mtk10 { color: #4EC9B0; }\n</style>","frontmatter":{"date":"February 09, 2016","updated_date":null,"description":null,"title":"Extended LinkedIn API Usage","tags":["LinkedIn","SocialLogin"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1,"src":"/static/a4e74ae24ffd6c107fe96587b9ac68eb/630fb/linkedin-feat-img.png","srcSet":"/static/a4e74ae24ffd6c107fe96587b9ac68eb/69585/linkedin-feat-img.png 200w,\n/static/a4e74ae24ffd6c107fe96587b9ac68eb/630fb/linkedin-feat-img.png 300w","sizes":"(max-width: 300px) 100vw, 300px"}}},"author":{"id":"Karl Wittig","github":null,"avatar":null}}}},{"node":{"excerpt":"If you're not familiar with Angular I'd highly recommend heading over to the Angular JS resource site and checking out what all the fuss is…","fields":{"slug":"/engineering/angular-roster-tutorial/"},"html":"<p>If you're not familiar with Angular I'd highly recommend heading over to the <a href=\"https://angularjs.org/\">Angular JS</a> resource site and checking out what all the fuss is about. Once you've got a basic understanding of Angular and how to get it up and running this tutorial will show you some of the basic, but awesome features supported by Angular.</p>\n<p>Today I'm going to be building out a roster for my fantasy football team. If that's not your cup of tea then by all means feel free to substitute the content for whatever floats your boat.</p>\n<h2 id=\"players-array\" style=\"position:relative;\"><a href=\"#players-array\" aria-label=\"players array permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Players Array</h2>\n<p>There might not be an I in team, but there are certainly players, so before we do anything in the HTML we'll have to make all the necessary components in the controller. First up let's make an array of all the players we want to include (initially at least) on our team.</p>\n<p>Every player is a special little snowflake, and our player objects should reflect that! With this in mind we will make each player an object with his or her own properties like: name, position and team. Here's an example of what our array might look like.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"0\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">$scope</span><span class=\"mtk1\">.</span><span class=\"mtk12\">players</span><span class=\"mtk1\"> = [</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    {</span><span class=\"mtk12\">name:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Tom Brady&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">position:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;QB&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">team:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Patriots&quot;</span><span class=\"mtk1\">},</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    {</span><span class=\"mtk12\">name:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Tony Romo&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">position:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;QB&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">team:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Cowboys&quot;</span><span class=\"mtk1\">},</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    {</span><span class=\"mtk12\">name:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Peyton Manning&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">position:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;QB&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">team:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Broncos&quot;</span><span class=\"mtk1\">},</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    {</span><span class=\"mtk12\">name:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Rob Gronkowsi&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">position:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;TE&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">team:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Patriots&quot;</span><span class=\"mtk1\">},</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    {</span><span class=\"mtk12\">name:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;JJ Watt&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">position:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;DE&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">team:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Texans&quot;</span><span class=\"mtk1\">},</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    {</span><span class=\"mtk12\">name:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Lavonte David&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">position:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;LB&quot;</span><span class=\"mtk1\">, </span><span class=\"mtk12\">team:</span><span class=\"mtk1\"> </span><span class=\"mtk8\">&quot;Buccaneers&quot;</span><span class=\"mtk1\">}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">];</span></span></code></pre>\n<h2 id=\"repetitive-department-of-repetition\" style=\"position:relative;\"><a href=\"#repetitive-department-of-repetition\" aria-label=\"repetitive department of repetition permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Repetitive department of repetition</h2>\n<p>Now that we have our roster we can go back to the HTML and make use of Angular's ng-repeat directive. We put the ng-repeat on the element we want to be repeated, keeping in mind that all of its children will also get repeated.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"1\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!--</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    {{</span><span class=\"mtk12\">player</span><span class=\"mtk1\">.</span><span class=\"mtk12\">name</span><span class=\"mtk1\">}} - {{</span><span class=\"mtk12\">player</span><span class=\"mtk1\">.</span><span class=\"mtk12\">position</span><span class=\"mtk1\">}}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">--&gt;</span></span></code></pre>\n<p>Okay so if you're new to Angular there's a couple of things going on here. First like I said we've got the ng-repeat placed on the li (the thing we want repeated) which will create a new li for each player in the players array we defined earlier in the controller. Next up the data binding is being implemented here with each player name as well as position being used as the values for the list item.</p>\n<p>While we're on the topic of data binding, let's throw this in just for fun. Pretty simple, it will calculate the length of your roster and keep it updated as any changes are made.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"2\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!--</span><span class=\"mtk12\">You</span><span class=\"mtk1\"> </span><span class=\"mtk12\">have</span><span class=\"mtk1\"> {{</span><span class=\"mtk12\">players</span><span class=\"mtk1\">.</span><span class=\"mtk12\">length</span><span class=\"mtk1\">}} </span><span class=\"mtk12\">on</span><span class=\"mtk1\"> </span><span class=\"mtk12\">your</span><span class=\"mtk1\"> </span><span class=\"mtk12\">roster</span><span class=\"mtk1\">.--&gt;</span></span></code></pre>\n<h2 id=\"easiest-search-functionality-of-your-life\" style=\"position:relative;\"><a href=\"#easiest-search-functionality-of-your-life\" aria-label=\"easiest search functionality of your life permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Easiest Search Functionality of Your Life</h2>\n<p>Next let's add some search functionality to our list. Sounds like a lot of work, probably have to iterate over the array elements, match them to the argument being passed in and... just kidding. With Angular it's a breeze.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"3\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!--</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">...</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">{{</span><span class=\"mtk12\">player</span><span class=\"mtk1\">.</span><span class=\"mtk12\">name</span><span class=\"mtk1\">}} - {{</span><span class=\"mtk12\">player</span><span class=\"mtk1\">.</span><span class=\"mtk12\">position</span><span class=\"mtk1\">}}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">--&gt;</span></span></code></pre>\n<p>Donezo.</p>\n<h2 id=\"the-shape-of-italy\" style=\"position:relative;\"><a href=\"#the-shape-of-italy\" aria-label=\"the shape of italy permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>The shape of Italy</h2>\n<p>Let's imagine one of our fantasy players isn't performing too well (ahem Peyton...) and we want to give him the boot (get it now?).</p>\n<p>We'll add a little delete button beside each of our players' names, and since we're doing it for each of them guess how we're going to implement it? That's right with ng-repeat we already have on the list items!</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"4\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!--{{</span><span class=\"mtk12\">player</span><span class=\"mtk1\">.</span><span class=\"mtk12\">name</span><span class=\"mtk1\">}} - {{</span><span class=\"mtk12\">player</span><span class=\"mtk1\">.</span><span class=\"mtk12\">position</span><span class=\"mtk1\">}}</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    ×</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">--&gt;</span></span></code></pre>\n<p>I'll also tack on a little button with an \"x\" as the content (as a side note, when you want to do this use × instead of \"x\" it looks much nicer). Then we'll attach an ng-click with a delete function where we pass in $index.</p>\n<p>$index is a neat little feature available with certain Angular directives, and ng-repeat is one of them. It will be assigned the index value (starting at 0) of the position it holds within the array being used with the ng-repeat.</p>\n<p>That's all we need in the HTML, so now back in the controller we create a $scope function by the same name used in the HTML and give it a parameter of index. The body of the function is a single line which makes use of the array.splice method where we pass in the index of the item we want to delete, and then 1 to denote that it's only 1 item we want removed.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"5\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">$scope</span><span class=\"mtk1\">.</span><span class=\"mtk11\">delete</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">function</span><span class=\"mtk1\"> (</span><span class=\"mtk12\">index</span><span class=\"mtk1\">) {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">$scope</span><span class=\"mtk1\">.</span><span class=\"mtk12\">players</span><span class=\"mtk1\">.</span><span class=\"mtk11\">splice</span><span class=\"mtk1\">(</span><span class=\"mtk12\">index</span><span class=\"mtk1\">, </span><span class=\"mtk7\">1</span><span class=\"mtk1\">);</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">};</span></span></code></pre>\n<h2 id=\"acquisitions\" style=\"position:relative;\"><a href=\"#acquisitions\" aria-label=\"acquisitions permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Acquisitions</h2>\n<p>Now since we just cut someone from the team, we've gotta find their replacement. Let's chuck a few text inputs in there, give them all a respective ng-model to bind with their value and finally another button with an ng-click but this time calling an addPlayer function.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"6\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk1\">&lt;!--</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    Name:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    Position:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    Team:</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">Add</span><span class=\"mtk1\"> </span><span class=\"mtk12\">Player</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">--&gt;</span></span></code></pre>\n<p>This one's a lil' different from delete, but still super simple. Working from the inside out, we will create a new player object which gets the name, position and team properties from the ng-models on the HTML and then push that object to the players array. After that we clear those values just for some good housekeeping practice.</p>\n<pre class=\"grvsc-container dark-default-dark\" data-language=\"js\" data-index=\"7\"><code class=\"grvsc-code\"><span class=\"grvsc-line\"><span class=\"mtk12\">$scope</span><span class=\"mtk1\">.</span><span class=\"mtk11\">add</span><span class=\"mtk1\"> = </span><span class=\"mtk4\">function</span><span class=\"mtk1\"> () {</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">$scope</span><span class=\"mtk1\">.</span><span class=\"mtk12\">players</span><span class=\"mtk1\">.</span><span class=\"mtk11\">push</span><span class=\"mtk1\">({</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">name:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">$scope</span><span class=\"mtk1\">.</span><span class=\"mtk12\">new_name</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">position:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">$scope</span><span class=\"mtk1\">.</span><span class=\"mtk12\">new_position</span><span class=\"mtk1\">,</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">        </span><span class=\"mtk12\">team:</span><span class=\"mtk1\"> </span><span class=\"mtk12\">$scope</span><span class=\"mtk1\">.</span><span class=\"mtk12\">new_team</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    });</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">$scope</span><span class=\"mtk1\">.</span><span class=\"mtk12\">new_name</span><span class=\"mtk1\"> = </span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">$scope</span><span class=\"mtk1\">.</span><span class=\"mtk12\">new_position</span><span class=\"mtk1\"> = </span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">    </span><span class=\"mtk12\">$scope</span><span class=\"mtk1\">.</span><span class=\"mtk12\">new_team</span><span class=\"mtk1\"> = </span><span class=\"mtk8\">&quot;&quot;</span><span class=\"mtk1\">;</span></span>\n<span class=\"grvsc-line\"><span class=\"mtk1\">};</span></span></code></pre>\n<h2 id=\"nothing-lasts-forever\" style=\"position:relative;\"><a href=\"#nothing-lasts-forever\" aria-label=\"nothing lasts forever permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Nothing Lasts Forever</h2>\n<p>Now since this was all done purely on the front end, and didn't make use of cookies, localstorage, or sessionstorage none of this will persist (aka be saved). For that kind of support you'd need some sort of back end, which is beyond the scope of this article.</p>\n<p>This was a very rudimentary example of what's possible with Angular JS, so if this interested you at all please dig a little deeper and play around with Angular some more!</p>\n<p>That brings us to the end of this tutorial. Feel free to check out the finished (yet unstyled) product <a href=\"https://codepen.io/anon/pen/pgoJwq\">here on Codepen</a></p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n  .dark-default-dark {\n    background-color: #1E1E1E;\n    color: #D4D4D4;\n  }\n  .dark-default-dark .mtk12 { color: #9CDCFE; }\n  .dark-default-dark .mtk1 { color: #D4D4D4; }\n  .dark-default-dark .mtk8 { color: #CE9178; }\n  .dark-default-dark .mtk11 { color: #DCDCAA; }\n  .dark-default-dark .mtk4 { color: #569CD6; }\n  .dark-default-dark .mtk7 { color: #B5CEA8; }\n</style>","frontmatter":{"date":"January 12, 2016","updated_date":null,"description":null,"title":"Angular Roster Tutorial","tags":["Engineering","AngularJS","PlayersArray","Array","Search"],"pinned":null,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1,"src":"/static/2773860898be140904449814ad319431/ee604/roster-angularjs-1.png","srcSet":"/static/2773860898be140904449814ad319431/69585/roster-angularjs-1.png 200w,\n/static/2773860898be140904449814ad319431/497c6/roster-angularjs-1.png 400w,\n/static/2773860898be140904449814ad319431/ee604/roster-angularjs-1.png 800w,\n/static/2773860898be140904449814ad319431/40ffe/roster-angularjs-1.png 960w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Zakary Hughes","github":null,"avatar":null}}}}]},"markdownRemark":{"excerpt":"Identity is evolving, and developers are at the forefront of this transformation. Every day brings a new learning—adapting to new standards…","fields":{"slug":"/identity/developer-first-identity-provider-loginradius/"},"html":"<p>Identity is evolving, and developers are at the forefront of this transformation. Every day brings a new learning—adapting to new standards and refining approaches to building secure, seamless experiences.</p>\n<p>We’re here to support developers on that journey. We know how important simplicity, efficiency, and well-structured documentation are when working with identity and access management solutions. That’s why we’ve redesigned the <a href=\"https://www.loginradius.com/\">LoginRadius website</a>—to be faster, more intuitive, and developer-first in every way.</p>\n<p>The goal? Having them spend less time searching and more time building.</p>\n<h2 id=\"whats-new-and-improved-on-the-loginradius-website\" style=\"position:relative;\"><a href=\"#whats-new-and-improved-on-the-loginradius-website\" aria-label=\"whats new and improved on the loginradius website permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>What’s New and Improved on the LoginRadius Website?</h2>\n<p>LoginRadius’ vision is to give developers a product that simplifies identity management so they can focus on building, deploying, and scaling their applications. To enhance this experience, we’ve spent the last few months redesigning our interface— making navigation more intuitive and reassuring that essential resources are easily accessible.</p>\n<p>Here’s a closer look at what’s new and why it’s important:</p>\n<h3 id=\"a-developer-friendly-dark-theme\" style=\"position:relative;\"><a href=\"#a-developer-friendly-dark-theme\" aria-label=\"a developer friendly dark theme permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>A Developer-Friendly Dark Theme</h3>\n<p><img src=\"/f46881583c7518a93bb24e94c32320de/a-developer-friendly-dark-theme.webp\" alt=\"This image shows how LoginRadius offers several authentication methods like traditional login, social login, passwordless login, passkeys and more in a dark mode.\">    </p>\n<p>Developers spend long hours working in dark-themed IDEs and terminals, so we’ve designed the LoginRadius experience to be developer-friendly and align with that preference.</p>\n<p>The new dark mode reduces eye strain, enhances readability, and provides a seamless transition between a coding environment and our platform. Our new design features a clean, modern aesthetic with a consistent color scheme and Barlow typography, ensuring better readability. High-quality graphics and icons are thoughtfully placed to enhance the content without adding visual clutter.</p>\n<p>So, whether you’re navigating our API docs or configuring authentication into your system, our improved interface will make those extended development hours more comfortable and efficient.</p>\n<h3 id=\"clear-categorization-for-loginradius-capabilities\" style=\"position:relative;\"><a href=\"#clear-categorization-for-loginradius-capabilities\" aria-label=\"clear categorization for loginradius capabilities permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Clear Categorization for LoginRadius Capabilities</h3>\n<p><img src=\"/e5358b82be414940f3fb146013845933/capabilities.webp\" alt=\"This image shows a breakdown of all the LoginRadius CIAM capabilities, including authentication, security, UX, scalability and multi-brand management.\"></p>\n<p>We’ve restructured our website to provide a straightforward breakdown of our customer identity and access management platform capabilities, helping you quickly find what you need:</p>\n<ul>\n<li>Authentication: Easily understand <a href=\"https://www.loginradius.com/blog/identity/authentication-option-for-your-product/\">how to choose the right login method</a>, from traditional passwords and OTPs to social login, federated SSO, and passkeys with few lines of code.</li>\n<li>Security: Implement no-code security features like bot detection, IP throttling, breached password alerts, DDoS protection, and adaptive MFA to safeguard user accounts.</li>\n<li>User Experience: Leverage AI builder, hosted pages, and drag-and-drop workflows to create smooth, branded sign-up and login experiences.</li>\n<li>High Performance &#x26; Scalability: Confidently scale with sub-100ms API response times, 100% uptime, 240K+ RPS, and 28+ global data center regions.</li>\n<li>Multi-Brand Management: Efficiently manage multiple identity apps, choosing isolated or shared data stores based on your brand’s unique needs.</li>\n</ul>\n<p>This structured layout ensures you can quickly understand each capability and how it integrates into your identity ecosystem.</p>\n<h3 id=\"developer-first-navigation\" style=\"position:relative;\"><a href=\"#developer-first-navigation\" aria-label=\"developer first navigation permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Developer-First Navigation</h3>\n<p><img src=\"/a8c155c2b6faf3d5f4b4de4e2b14d763/developers-menu.webp\" alt=\"This image shows the LoginRadius menu bar, highlighting the developer dropdown.\">   </p>\n<p>We’ve been analyzing developer workflows to identify how you access key resources. That’s why we redesigned our navigation with one goal in mind: to reduce clicks and make essential resources readily available.</p>\n<p>The new LoginRadius structure puts APIs, SDKs, and integration guides right at the menu bar under the Developers dropdown so you can get started faster. Our Products, Solutions, and Customer Services are also clearly categorized, helping development teams quickly find the right tools and make informed decisions.</p>\n<h3 id=\"quick-understanding-of-integration-benefits\" style=\"position:relative;\"><a href=\"#quick-understanding-of-integration-benefits\" aria-label=\"quick understanding of integration benefits permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Quick Understanding of Integration Benefits</h3>\n<p><img src=\"/b2f9a964a2da0ea83e2f8596b833bba7/we-support-your-tech-stack.webp\" alt=\"This image shows a list of popular programming languages and frameworks offered by LoginRadius.\"></p>\n<p>Developers now have a clear view of the tech stack available with LoginRadius, designed to support diverse business needs.</p>\n<p>Our platform offers pre-built SDKs for Node.js, Python, Java, and more, making CIAM integration seamless across popular programming languages and frameworks.</p>\n<h2 id=\"over-to-you-now\" style=\"position:relative;\"><a href=\"#over-to-you-now\" aria-label=\"over to you now permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Over to You Now!</h2>\n<p>Check out our <a href=\"https://www.loginradius.com/\">revamped LoginRadius website</a> and see how the improved experience makes it easier to build, scale, and secure your applications.</p>\n<p>Do not forget to explore the improved navigation and API documentation, and get started with our free trial today. We’re excited to see what you’ll build with LoginRadius!</p>\n<style class=\"grvsc-styles\">\n  .grvsc-container {\n    overflow: auto;\n    -webkit-overflow-scrolling: touch;\n    padding-top: 1rem;\n    padding-top: var(--grvsc-padding-top, var(--grvsc-padding-v, 1rem));\n    padding-bottom: 1rem;\n    padding-bottom: var(--grvsc-padding-bottom, var(--grvsc-padding-v, 1rem));\n    border-radius: 8px;\n    border-radius: var(--grvsc-border-radius, 8px);\n    font-feature-settings: normal;\n  }\n  \n  .grvsc-code {\n    display: inline-block;\n    min-width: 100%;\n  }\n  \n  .grvsc-line {\n    display: inline-block;\n    box-sizing: border-box;\n    width: 100%;\n    padding-left: 1.5rem;\n    padding-left: var(--grvsc-padding-left, var(--grvsc-padding-h, 1.5rem));\n    padding-right: 1.5rem;\n    padding-right: var(--grvsc-padding-right, var(--grvsc-padding-h, 1.5rem));\n  }\n  \n  .grvsc-line-highlighted {\n    background-color: var(--grvsc-line-highlighted-background-color, transparent);\n    box-shadow: inset var(--grvsc-line-highlighted-border-width, 4px) 0 0 0 var(--grvsc-line-highlighted-border-color, transparent);\n  }\n  \n</style>","frontmatter":{"date":"February 21, 2025","updated_date":null,"description":"LoginRadius’ vision is to give developers a product that simplifies identity management so they can focus on building, deploying, and scaling their applications. To enhance this experience, we’ve redesigned our website interface, making navigation more intuitive and reassuring that essential resources are easily accessible.","title":"Revamped & Ready: Introducing the New Developer-First LoginRadius Website","tags":["Developer tools","API","Identity Management","User Authentication"],"pinned":true,"coverImage":{"childImageSharp":{"fluid":{"aspectRatio":1.7857142857142858,"src":"/static/80b4e4fbe176a10a327d273504607f32/58556/hero-section.webp","srcSet":"/static/80b4e4fbe176a10a327d273504607f32/61e93/hero-section.webp 200w,\n/static/80b4e4fbe176a10a327d273504607f32/1f5c5/hero-section.webp 400w,\n/static/80b4e4fbe176a10a327d273504607f32/58556/hero-section.webp 800w,\n/static/80b4e4fbe176a10a327d273504607f32/99238/hero-section.webp 1200w,\n/static/80b4e4fbe176a10a327d273504607f32/7c22d/hero-section.webp 1600w,\n/static/80b4e4fbe176a10a327d273504607f32/1258b/hero-section.webp 2732w","sizes":"(max-width: 800px) 100vw, 800px"}}},"author":{"id":"Rakesh Soni","github":"oyesoni","avatar":"rakesh-soni.jpg"}}}},"pageContext":{"limit":6,"skip":906,"currentPage":152,"type":"///","numPages":161,"pinned":"ee8a4479-3471-53b1-bf62-d0d8dc3faaeb"}},"staticQueryHashes":["1171199041","1384082988","2100481360","23180105","528864852"]}