{"_id":"53fe7e08addab8973c1af2b9","user":"53fe6d8baddab8973c1af266","version":{"_id":"53fe6dc5addab8973c1af26a","__v":19,"project":"53fe6dc5addab8973c1af267","createdAt":"2014-08-27T23:46:13.941Z","releaseDate":"2014-08-27T23:46:13.941Z","categories":["53fe6dc5addab8973c1af26b","53fe71a2addab8973c1af276","53fe7d89addab8973c1af2b0","53fe7d8daddab8973c1af2b1","53fe836faddab8973c1af2ce","53ff9a4823a37e1d5cebafe1","53ff9e3723a37e1d5cebaff7","53ffaca523a37e1d5cebb039","53ffad2e23a37e1d5cebb03c","5400c7d2ec93b29b61d4f7be","5400f0e1ec93b29b61d4f7dd","54d5636323010a0d001aca81","54d565c1276f8e0d00feab54","54ff40532882a10d00546927","556606d25561af0d008208b7","558c91900b236c2500d37c9a","56180a14f8c9632100ac7599","564fb3a59b4fab1700187518","5702e2d2f2d6f336005e901f"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"1.0.0","version":"1.0"},"__v":15,"tags":[],"category":{"_id":"53fe7d8daddab8973c1af2b1","project":"53fe6dc5addab8973c1af267","__v":5,"version":"53fe6dc5addab8973c1af26a","pages":["53fe732eaddab8973c1af27f","53fe7df4addab8973c1af2b7","53fe7e08addab8973c1af2b9","544945633acc37080099e719","551c450c0360770d00f5ce3a"],"sync":{"url":"","isSync":false},"reference":false,"createdAt":"2014-08-28T00:53:33.662Z","from_sync":false,"order":5,"slug":"login-reference","title":"Login Reference"},"is_link":false,"comments":[],"parentDoc":null,"project":"53fe6dc5addab8973c1af267","updates":[],"next":{"pages":[],"description":""},"createdAt":"2014-08-28T00:55:36.953Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","try":true,"auth":"never","params":[],"url":""},"isReference":false,"order":2,"body":"You can associate Clef logins with users in your database by storing the `clef_id` that you received by completing the OAuth handshake. The `clef_id` is a numeric identifier that is unique to a user and your website.\n\n# Updating your User model\n\nIn your database, add a column to your `User` model to store the `clef_id`. In a SQL database, you can do this like so: \n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"ALTER TABLE user ADD clef_id bigint(20);\",\n      \"language\": \"mysql\"\n    }\n  ]\n}\n[/block]\n# Registering new users\n\nIf a Clef user is logging into your site for the very first time, they'll be asked permission to pass information to your site. You'll receive this user information along with the `clef_id` in the `info` object upon completion of the OAuth handshake. You can specify which information you would like to receive when you create your Clef App ID and App Secret.  \n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"Most integrations ask users for their email addresses to send transactional emails. Keep in mind that the `clef_id` is *always* passed, so if you don't need to send emails, your website may not need any additional user information.\",\n  \"title\": \"Keep it simple\"\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"# Create a new user that's persisted in the database\\nuser = User.create(\\n  :email => info['email'],\\n  :clef_id => info['clef_id']\\n)\\n\\n# Store a cookie indicating that the user is logged in\\nsession[:user] = user.id\",\n      \"language\": \"ruby\"\n    },\n    {\n      \"code\": \"# Create a new user and save in the database\\nuser = User(email=info['email'], clef_id=info['clef_id'])\\ndb.session.add(user)\\ndb.session.commit()\\n\\n# Store a cookie indicating that the user is logged in\\nsession['user'] = user.id\",\n      \"language\": \"python\"\n    },\n    {\n      \"code\": \"<?php\\n$clef_id = $info['clef_id'];\\n$email = $info['email'];\\n\\nif (!($stmt = $mysqli->prepare(\\\"INSERT INTO user (email, clef_id) VALUES (?, ?)\\\"))) {\\n     echo \\\"Prepare failed: (\\\" . $mysqli->errno . \\\") \\\" . $mysqli->error;\\n}\\n\\nif (!$stmt->bind_param(\\\"si\\\", $email, $clef_id)) {\\n   echo \\\"Binding parameters failed: (\\\" . $stmt->errno . \\\") \\\" . $stmt->error;\\n}\\n\\nif (!$stmt->execute()) {\\n    echo \\\"Execute failed: (\\\" . $stmt->errno . \\\") \\\" . $stmt->error;\\n}\\n\\n$stmt->close();\\n\\n$_SESSION['user'] = $mysql->last_id;\\n?>\",\n      \"language\": \"php\"\n    }\n  ]\n}\n[/block]\n\n\n# Associating existing users\n\nIf you're adding Clef to a website with existing users, you'll want to provide a way to link existing users with their Clef accounts. The easiest way to do this is to allow users to link their Clef account after they have already signed in. You can render a Clef button in a settings panel and handle the OAuth handshake differently by redirecting to a different redirect URL or by checking whether there is a user already in the current session in your existing logic. \n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"user.update(:clef_id => info['clef_id'])\",\n      \"language\": \"ruby\"\n    },\n    {\n      \"code\": \"user.clef_id = info['clef_id']\\ndb.session.add(user)\\ndb.session.commit()\",\n      \"language\": \"python\"\n    },\n    {\n      \"code\": \"<?php\\n$clef_id = $user_info['clef_id'];\\n\\nif (!($stmt = $mysqli->prepare(\\\"UPDATE user SET clef_id = ? WHERE id = ?\\\"))) {\\n     echo \\\"Prepare failed: (\\\" . $mysqli->errno . \\\") \\\" . $mysqli->error;\\n}\\n\\nif (!$stmt->bind_param(\\\"ii\\\", $user_id, $clef_id)) {\\n   echo \\\"Binding parameters failed: (\\\" . $stmt->errno . \\\") \\\" . $stmt->error;\\n}\\n\\nif (!$stmt->execute()) {\\n    echo \\\"Execute failed: (\\\" . $stmt->errno . \\\") \\\" . $stmt->error;\\n}\\n\\n$stmt->close();\\n?>\",\n      \"language\": \"php\"\n    }\n  ]\n}\n[/block]\nAfter associating an existing user with their Clef account, you can look the user up next time they log in to your site with Clef. \n\n### Verifying the `state` parameter\n\nTo protect against CSRF attacks, you should *always* pass in a `state` parameter to either the Clef button (with `data-state`) or the Clef login URL (by specifying `&state=` in the URL). In the handshake, this `state` parameter will be passed back and you'll need to verify that it is the same as the one you passed in.\n\n**This check is especially important if you are connecting Clef to an already existing account. If it's not implemented correctly, it can lead to [\"The Most Common OAuth2 Vulnerability\"](http://homakov.blogspot.com/2012/07/saferweb-most-common-oauth2.html).**\n\nYou can read more about how to do this [here](doc:verifying-state-parameter).\n\n# Retrieving users\n\nWith the `clef_id` in hand and your `User` model updated, retrieving users from your database is a simple query. \n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"# Look a user up by their clef_id\\nuser = User.first(:clef_id => info['clef_id'])\\n\\n# Store a cookie indicating that the user is logged in\\nsession[:user] = user.id\",\n      \"language\": \"ruby\"\n    },\n    {\n      \"code\": \"# Look a user up by their clef_id\\nuser = User.query.filter_by(clef_id=info['clef_id']).first()\\n\\n# Store a cookie indicating that the user is logged in\\nsession['user'] = user.id\",\n      \"language\": \"python\"\n    },\n    {\n      \"code\": \"<?php\\n$clef_id = $user_info['clef_id'];\\n\\nif (!($stmt = $mysqli->prepare(\\\"SELECT * FROM user WHERE clef_id = ?\\\"))) {\\n     echo \\\"Prepare failed: (\\\" . $mysqli->errno . \\\") \\\" . $mysqli->error;\\n}\\n\\nif (!$stmt->bind_param(\\\"i\\\", $clef_id)) {\\n   echo \\\"Binding parameters failed: (\\\" . $stmt->errno . \\\") \\\" . $stmt->error;\\n}\\n\\n$stmt->execute();\\n$res = $stmt->get_result();\\n$row = $res->fetch_assoc();\\n$stmt->close();\\n\\n$_SESSION['user'] = $row['id'];\\n?>\",\n      \"language\": \"php\"\n    }\n  ]\n}\n[/block]\n# Combining registration and retrieval\n\nIn most cases, you'll want to combine your logic for creating new users who register with Clef and looking up existing users who log in with Clef. You can do this by querying for an existing user by `clef_id` and creating one if they don't already exist.\n\n# Next up\nNow that you're done logging users in, you're ready to move on to [logout](/v1.0/docs/overview).\n[block:html]\n{\n  \"html\": \"<div></div>\\n<a class=\\\"clef-button blue\\\" href=\\\"/v1.0/docs/overview\\\">Go to the next section</a>\\n<style></style>\"\n}\n[/block]","excerpt":"After retrieving information from Clef, you can create new users and identify them when they log in next time.","slug":"persisting-users","type":"basic","title":"Associating users"}

Associating users

After retrieving information from Clef, you can create new users and identify them when they log in next time.

You can associate Clef logins with users in your database by storing the `clef_id` that you received by completing the OAuth handshake. The `clef_id` is a numeric identifier that is unique to a user and your website. # Updating your User model In your database, add a column to your `User` model to store the `clef_id`. In a SQL database, you can do this like so: [block:code] { "codes": [ { "code": "ALTER TABLE user ADD clef_id bigint(20);", "language": "mysql" } ] } [/block] # Registering new users If a Clef user is logging into your site for the very first time, they'll be asked permission to pass information to your site. You'll receive this user information along with the `clef_id` in the `info` object upon completion of the OAuth handshake. You can specify which information you would like to receive when you create your Clef App ID and App Secret. [block:callout] { "type": "info", "body": "Most integrations ask users for their email addresses to send transactional emails. Keep in mind that the `clef_id` is *always* passed, so if you don't need to send emails, your website may not need any additional user information.", "title": "Keep it simple" } [/block] [block:code] { "codes": [ { "code": "# Create a new user that's persisted in the database\nuser = User.create(\n :email => info['email'],\n :clef_id => info['clef_id']\n)\n\n# Store a cookie indicating that the user is logged in\nsession[:user] = user.id", "language": "ruby" }, { "code": "# Create a new user and save in the database\nuser = User(email=info['email'], clef_id=info['clef_id'])\ndb.session.add(user)\ndb.session.commit()\n\n# Store a cookie indicating that the user is logged in\nsession['user'] = user.id", "language": "python" }, { "code": "<?php\n$clef_id = $info['clef_id'];\n$email = $info['email'];\n\nif (!($stmt = $mysqli->prepare(\"INSERT INTO user (email, clef_id) VALUES (?, ?)\"))) {\n echo \"Prepare failed: (\" . $mysqli->errno . \") \" . $mysqli->error;\n}\n\nif (!$stmt->bind_param(\"si\", $email, $clef_id)) {\n echo \"Binding parameters failed: (\" . $stmt->errno . \") \" . $stmt->error;\n}\n\nif (!$stmt->execute()) {\n echo \"Execute failed: (\" . $stmt->errno . \") \" . $stmt->error;\n}\n\n$stmt->close();\n\n$_SESSION['user'] = $mysql->last_id;\n?>", "language": "php" } ] } [/block] # Associating existing users If you're adding Clef to a website with existing users, you'll want to provide a way to link existing users with their Clef accounts. The easiest way to do this is to allow users to link their Clef account after they have already signed in. You can render a Clef button in a settings panel and handle the OAuth handshake differently by redirecting to a different redirect URL or by checking whether there is a user already in the current session in your existing logic. [block:code] { "codes": [ { "code": "user.update(:clef_id => info['clef_id'])", "language": "ruby" }, { "code": "user.clef_id = info['clef_id']\ndb.session.add(user)\ndb.session.commit()", "language": "python" }, { "code": "<?php\n$clef_id = $user_info['clef_id'];\n\nif (!($stmt = $mysqli->prepare(\"UPDATE user SET clef_id = ? WHERE id = ?\"))) {\n echo \"Prepare failed: (\" . $mysqli->errno . \") \" . $mysqli->error;\n}\n\nif (!$stmt->bind_param(\"ii\", $user_id, $clef_id)) {\n echo \"Binding parameters failed: (\" . $stmt->errno . \") \" . $stmt->error;\n}\n\nif (!$stmt->execute()) {\n echo \"Execute failed: (\" . $stmt->errno . \") \" . $stmt->error;\n}\n\n$stmt->close();\n?>", "language": "php" } ] } [/block] After associating an existing user with their Clef account, you can look the user up next time they log in to your site with Clef. ### Verifying the `state` parameter To protect against CSRF attacks, you should *always* pass in a `state` parameter to either the Clef button (with `data-state`) or the Clef login URL (by specifying `&state=` in the URL). In the handshake, this `state` parameter will be passed back and you'll need to verify that it is the same as the one you passed in. **This check is especially important if you are connecting Clef to an already existing account. If it's not implemented correctly, it can lead to ["The Most Common OAuth2 Vulnerability"](http://homakov.blogspot.com/2012/07/saferweb-most-common-oauth2.html).** You can read more about how to do this [here](doc:verifying-state-parameter). # Retrieving users With the `clef_id` in hand and your `User` model updated, retrieving users from your database is a simple query. [block:code] { "codes": [ { "code": "# Look a user up by their clef_id\nuser = User.first(:clef_id => info['clef_id'])\n\n# Store a cookie indicating that the user is logged in\nsession[:user] = user.id", "language": "ruby" }, { "code": "# Look a user up by their clef_id\nuser = User.query.filter_by(clef_id=info['clef_id']).first()\n\n# Store a cookie indicating that the user is logged in\nsession['user'] = user.id", "language": "python" }, { "code": "<?php\n$clef_id = $user_info['clef_id'];\n\nif (!($stmt = $mysqli->prepare(\"SELECT * FROM user WHERE clef_id = ?\"))) {\n echo \"Prepare failed: (\" . $mysqli->errno . \") \" . $mysqli->error;\n}\n\nif (!$stmt->bind_param(\"i\", $clef_id)) {\n echo \"Binding parameters failed: (\" . $stmt->errno . \") \" . $stmt->error;\n}\n\n$stmt->execute();\n$res = $stmt->get_result();\n$row = $res->fetch_assoc();\n$stmt->close();\n\n$_SESSION['user'] = $row['id'];\n?>", "language": "php" } ] } [/block] # Combining registration and retrieval In most cases, you'll want to combine your logic for creating new users who register with Clef and looking up existing users who log in with Clef. You can do this by querying for an existing user by `clef_id` and creating one if they don't already exist. # Next up Now that you're done logging users in, you're ready to move on to [logout](/v1.0/docs/overview). [block:html] { "html": "<div></div>\n<a class=\"clef-button blue\" href=\"/v1.0/docs/overview\">Go to the next section</a>\n<style></style>" } [/block]