Login Form
All CUBA REST API methods require an OAuth token. In order to obtain this token the client must authenticate using user’s login and password. This mechanism is described in the Developer’s Manual.
The cuba-login web component allows you to create a login form. It’s a simple UI component with 2 fields ("User Name", "Password") and the "Login" button. It sends two events on login attempt: cuba-login-success
and cuba-login-error
.
Below is a working example, please use login test
and password test
.
Source code
<html>
<head>
<link rel="import" href="src/cuba/login/app-with-login.html">
<script src="bower_components/webcomponentsjs/webcomponents-loader.js"></script>
</head>
<body>
<app-with-login></app-with-login>
</body>
</html>
<link rel="import" href="../../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../../bower_components/polymer/lib/elements/dom-if.html">
<link rel="import" href="../../../bower_components/cuba-app/cuba-app.html">
<link rel="import" href="../../../bower_components/cuba-app/cuba-app-aware-behavior.html">
<link rel="import" href="../../../bower_components/cuba-login/cuba-login.html">
<dom-module id="app-with-login">
<template>
<!-- 'cuba-app' always should be the first thing in an application -->
<!-- uses CUBA REST API -->
<cuba-app api-url="/app/rest/"></cuba-app>
<template is="dom-if" if="[[!authenticated]]">
<!-- Only after the user is authenticated -->
<!-- the rest of the CUBA REST API can be used -->
<cuba-login on-cuba-login-success="_onLoginSuccess" on-cuba-login-error="_onLoginError"></cuba-login>
</template>
<template is="dom-if" if="[[authenticated]]">
<h3>Congratulations! You are authenticated and now can use cuba REST API!</h3>
<div>
<button on-click="_logout">Logout</button>
</div>
</template>
</template>
<script>
class AppWithLogin extends Polymer.mixinBehaviors([CubaAppAwareBehavior], Polymer.Element) {
static get is() {
return 'app-with-login';
}
static get properties() {
return {
authenticated: {
type: Boolean,
value: false
}
};
}
_onLoginSuccess() {
this.set('authenticated', true);
}
_logout() {
this.set('authenticated', false);
this.app.logout();
}
_onLoginError() {
alert('Bad credentials');
}
}
customElements.define(AppWithLogin.is, AppWithLogin);
</script>
</dom-module>
- Styling
-
If you check
cuba-login
source code, you can see that the component is opened for extension by using custom property mixins.bower_components/cuba-login/cuba-login.html#form { @apply --cuba-login-form; } #username { @apply --cuba-login-username-input; } #password { @apply --cuba-login-password-input; } #submit { @apply --cuba-login-submit-button; } .actions { display: flex; flex-direction: row-reverse; @apply --cuba-login-actions; } ... <form id="form"> <div class="fields"> <paper-input type="text" id="username" label="[[msg('User Name')]]" value="{{username}}"></paper-input> <paper-input type="password" id="password" label="[[msg('Password')]]" value="{{password}}"></paper-input> </div> <div class="actions"> <paper-button id="submit" on-tap="submit">[[msg('Login')]]</paper-button> </div> </form>
Below you can see how these mixins can be implemented. The example is the same as above but contains the
<style/>
section.src/cuba/login/app-with-login-styled.html<link rel="import" href="../../../bower_components/polymer/polymer-element.html"> <link rel="import" href="../../../bower_components/polymer/lib/elements/dom-if.html"> <link rel="import" href="../../../bower_components/cuba-app/cuba-app.html"> <link rel="import" href="../../../bower_components/cuba-app/cuba-app-aware-behavior.html"> <link rel="import" href="../../../bower_components/cuba-login/cuba-login.html"> <dom-module id="app-with-login-styled"> <template> <style> .login-form { /* That's how we define a mixin */ --cuba-login-form: { display: flex; justify-content: center; }; --cuba-login-actions: { padding: 5px; }; --cuba-login-submit-button: { border: black solid 1px; }; } </style> <cuba-app api-url="/app/rest/"></cuba-app> <template is="dom-if" if="[[!authenticated]]"> <cuba-login class="login-form" on-cuba-login-success="_onLoginSuccess" on-cuba-login-error="_onLoginError"></cuba-login> </template> <template is="dom-if" if="[[authenticated]]"> <h3>Congratulations! You are authenticated and now can use cuba REST API!</h3> <div> <button on-click="_logout">Logout</button> </div> </template> </template> <script> class AppWithLoginStyled extends Polymer.mixinBehaviors([CubaAppAwareBehavior], Polymer.Element) { static get is() { return 'app-with-login-styled'; } static get properties() { return { authenticated: { type: Boolean, value: false } }; } _onLoginSuccess() { this.set('authenticated', true); } _logout() { this.set('authenticated', false); this.app.logout(); } _onLoginError() { alert('Bad credentials'); } } customElements.define(AppWithLoginStyled.is, AppWithLoginStyled); </script> </dom-module>
Result of styling
- Writing your own login form
-
cuba-login
, as any other CUBA component usescuba-rest
component API under the hood. It means that if you need some very custom login page, you can use the API directly. See an example below.src/cuba/login/app-with-login-custom.html<link rel="import" href="../../../bower_components/polymer/polymer-element.html"> <link rel="import" href="../../../bower_components/polymer/lib/elements/dom-if.html"> <link rel="import" href="../../../bower_components/cuba-app/cuba-app.html"> <link rel="import" href="../../../bower_components/cuba-app/cuba-app-aware-behavior.html"> <dom-module id="app-with-login-custom"> <template> <cuba-app api-url="/app/rest/"></cuba-app> <template is="dom-if" if="[[!authenticated]]"> <label> Please choose your login: </label> <br/> <br/> <select id="typeSelect"> <option value="marketer">Marketer</option> <option value="manager">Manager</option> <option value="admin">Admin</option> </select> <br/> <br/> <button on-click="_login">Login</button> </template> <template is="dom-if" if="[[authenticated]]"> <h3>Congratulations! You are authenticated and now can use cuba REST API!</h3> <div> <button on-click="_logout">Logout</button> </div> </template> </template> <script> class AppWithLoginCustom extends Polymer.mixinBehaviors([CubaAppAwareBehavior], Polymer.Element) { static get is() { return 'app-with-login-custom'; } static get properties() { return { authenticated: { type: Boolean, value: false } }; } _login() { const login = this.shadowRoot.querySelector('#typeSelect').value; let password; // In accordance with the best security anti-patterns switch (login) { case 'marketer': password = 'marketer!'; break; case 'manager': password = 'manager:-)'; break; case 'admin': password = 'admin123'; break; } this.app.login(login, password).then(function() { this.set('authenticated', true); }.bind(this)); } _logout() { this.set('authenticated', false); this.app.logout(); } _onLoginError() { alert('Bad credentials'); } } customElements.define(AppWithLoginCustom.is, AppWithLoginCustom); </script> </dom-module>
Custom login form
- Token expiration
-
A Polymer application receives a token after authentication and then uses it with every request.
By default, a token is valid for 12 hours. After this period requests stop working and the user has to re-login. We recommend to increase the token expiration time and use the persistent token store to save tokens on server restart.
cuba-app
sends thecuba-token-expired
event that can be used to handle the expiration appropriately.