1
0
Fork 0
mirror of https://github.com/documize/community.git synced 2025-07-21 14:19:43 +02:00

sync users wip

This commit is contained in:
Harvey Kandola 2017-03-17 19:01:32 +00:00
parent 1c6e1c7bd7
commit 945fadaf00
6 changed files with 166 additions and 30 deletions

View file

@ -25,11 +25,15 @@ export default Ember.Component.extend({
KeycloakRealmError: computed.empty('keycloakConfig.realm'), KeycloakRealmError: computed.empty('keycloakConfig.realm'),
KeycloakClientIdError: computed.empty('keycloakConfig.clientId'), KeycloakClientIdError: computed.empty('keycloakConfig.clientId'),
KeycloakPublicKeyError: computed.empty('keycloakConfig.publicKey'), KeycloakPublicKeyError: computed.empty('keycloakConfig.publicKey'),
KeycloakAdminUserError: computed.empty('keycloakConfig.adminUser'),
KeycloakAdminPasswordError: computed.empty('keycloakConfig.adminPassword'),
keycloakConfig: { keycloakConfig: {
url: '', url: '',
realm: '', realm: '',
clientId: '', clientId: '',
publicKey: '', publicKey: '',
adminUser: '',
adminPassword: ''
}, },
didReceiveAttrs() { didReceiveAttrs() {
@ -89,16 +93,14 @@ export default Ember.Component.extend({
this.$("#keycloak-publicKey").focus(); this.$("#keycloak-publicKey").focus();
return; return;
} }
if (this.get('KeycloakAdminUserError')) {
// let pk = this.get('keycloakConfig.publicKey'); this.$("#keycloak-admin-user").focus();
// if (is.not.startWith(pk, '-----BEGIN PUBLIC KEY-----')) { return;
// pk = '-----BEGIN PUBLIC KEY-----' + pk; }
// } if (this.get('KeycloakAdminPasswordError')) {
// if (is.not.endWith(pk, '-----END PUBLIC KEY-----')) { this.$("#keycloak-admin-password").focus();
// pk = pk + '-----END PUBLIC KEY-----' ; return;
// } }
// this.set('keycloakConfig.publicKey', pk);
config = Ember.copy(this.get('keycloakConfig')); config = Ember.copy(this.get('keycloakConfig'));
Ember.set(config, 'publicKey', encoding.Base64.encode(this.get('keycloakConfig.publicKey'))); Ember.set(config, 'publicKey', encoding.Base64.encode(this.get('keycloakConfig.publicKey')));

View file

@ -15,7 +15,8 @@ import constants from '../../../utils/constants';
export default Ember.Route.extend({ export default Ember.Route.extend({
session: Ember.inject.service(), session: Ember.inject.service(),
appMeta: Ember.inject.service(), appMeta: Ember.inject.service(),
kcAuth: Ember.inject.service(), kcAuth: Ember.inject.service(),
localStorage: Ember.inject.service(),
queryParams: { queryParams: {
mode: { mode: {
refreshModel: false refreshModel: false
@ -33,11 +34,16 @@ export default Ember.Route.extend({
return; return;
} }
if (this.get('mode') === 'reject') {
return;
}
this.get('kcAuth').boot(JSON.parse(authConfig)).then((kc) => { this.get('kcAuth').boot(JSON.parse(authConfig)).then((kc) => {
if (!kc.authenticated) { if (!kc.authenticated) {
this.get('kcAuth').login().then(() => { this.get('kcAuth').login().then(() => {
}, (reject) => { }, (reject) => {
console.log(reject); this.get('localStorage').storeSessionItem('kc-error', reject);
this.transitionTo('auth.keycloak', { queryParams: { mode: 'reject' }});
}); });
} }
@ -47,16 +53,23 @@ export default Ember.Route.extend({
this.get('audit').record("logged-in-keycloak"); this.get('audit').record("logged-in-keycloak");
this.transitionTo('folders'); this.transitionTo('folders');
}, (reject) => { }, (reject) => {
debugger; this.get('localStorage').storeSessionItem('kc-error', reject);
console.log(">>>>> Documize Keycloak authentication failure"); this.transitionTo('auth.keycloak', { queryParams: { mode: 'reject' }});
this.transitionTo('auth.login');
}); });
}, (err) => { }, (reject) => {
console.log(err); this.get('localStorage').storeSessionItem('kc-error', reject);
this.transitionTo('auth.keycloak', { queryParams: { mode: 'reject' }});
}); });
}, (reason) => { }, (reject) => {
console.log(reason); this.get('localStorage').storeSessionItem('kc-error', reject);
this.transitionTo('auth.keycloak', { queryParams: { mode: 'reject' }});
}); });
}, },
model() {
return {
mode: this.get('mode')
}
}
}); });

View file

@ -1,4 +1,12 @@
<div class="sso-box"> {{#if (is-equal model.mode 'login')}}
<p>Authenticating with Keycloak...</p> <div class="sso-box">
<img src="/assets/img/busy-gray.gif" /> <p>Authenticating with Keycloak...</p>
</div> <img src="/assets/img/busy-gray.gif" />
</div>
{{/if}}
{{#if (is-equal model.mode 'reject')}}
<div class="sso-box">
<p>Keycloak Authentication Failure</p>
</div>
{{/if}}

View file

@ -15,6 +15,7 @@ import constants from '../../../utils/constants';
export default Ember.Route.extend({ export default Ember.Route.extend({
appMeta: Ember.inject.service(), appMeta: Ember.inject.service(),
kcAuth: Ember.inject.service(), kcAuth: Ember.inject.service(),
localStorage: Ember.inject.service(),
showLogin: false, showLogin: false,
beforeModel(/*transition*/) { beforeModel(/*transition*/) {
@ -28,13 +29,16 @@ export default Ember.Route.extend({
this.get('kcAuth').boot(JSON.parse(authConfig)).then(() => { this.get('kcAuth').boot(JSON.parse(authConfig)).then(() => {
this.get('kcAuth').login().then(() => { this.get('kcAuth').login().then(() => {
}, (reject) => { }, (reject) => {
console.log(reject); this.get('localStorage').storeSessionItem('kc-error', reject);
this.transitionTo('auth.keycloak', { queryParams: { mode: 'reject' }});
}); });
}, (reject) => { }, (reject) => {
console.log(reject); this.get('localStorage').storeSessionItem('kc-error', reject);
this.transitionTo('auth.keycloak', { queryParams: { mode: 'reject' }});
}); });
break; break;
default: default:
this.set('showLogin', true); this.set('showLogin', true);
break; break;

View file

@ -13,7 +13,7 @@
{{#if isKeycloakProvider}} {{#if isKeycloakProvider}}
<div class="form-header"> <div class="form-header">
<div class="title">Keycloak Configuration</div> <div class="title">Keycloak Configuration</div>
<div class="tip">Connection parameters</div> <div class="tip">Connection parameters &mdash; create a documize user in Master realm with 'manage-users' role against target realm</div>
</div> </div>
<div class="input-control"> <div class="input-control">
<label>Keycloak Server URL</label> <label>Keycloak Server URL</label>
@ -35,6 +35,16 @@
<div class="tip">Copy the RSA public key from Realm Settings &rarr; Keys</div> <div class="tip">Copy the RSA public key from Realm Settings &rarr; Keys</div>
{{textarea id="keycloak-publicKey" type="text" value=keycloakConfig.publicKey rows=7 class=(if KeycloakPublicKeyError 'error')}} {{textarea id="keycloak-publicKey" type="text" value=keycloakConfig.publicKey rows=7 class=(if KeycloakPublicKeyError 'error')}}
</div> </div>
<div class="input-control">
<label>Keycloak Username</label>
<div class="tip">Used to connect with Keycloak and sync users with Documize</div>
{{input id="keycloak-admin-user" type="text" value=keycloakConfig.adminUser class=(if KeycloakAdminUserError 'error')}}
</div>
<div class="input-control">
<label>Keycloak Password</label>
<div class="tip">Used to connect with Keycloak and sync users with Documize</div>
{{input id="keycloak-admin-password" type="password" value=keycloakConfig.adminPassword class=(if KeycloakAdminPasswordError 'error')}}
</div>
{{/if}} {{/if}}
<div class="regular-button button-blue" {{action 'onSave'}}>save</div> <div class="regular-button button-blue" {{action 'onSave'}}>save</div>

View file

@ -17,14 +17,18 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"net/url"
"strings" "strings"
"bytes"
"errors"
"github.com/documize/community/core/api/endpoint/models" "github.com/documize/community/core/api/endpoint/models"
"github.com/documize/community/core/api/entity" "github.com/documize/community/core/api/entity"
"github.com/documize/community/core/api/request" "github.com/documize/community/core/api/request"
"github.com/documize/community/core/api/util" "github.com/documize/community/core/api/util"
"github.com/documize/community/core/log" "github.com/documize/community/core/log"
"github.com/documize/community/core/utility" "github.com/documize/community/core/utility"
"strconv"
) )
// AuthenticateKeycloak checks Keycloak authentication credentials. // AuthenticateKeycloak checks Keycloak authentication credentials.
@ -158,6 +162,11 @@ func AuthenticateKeycloak(w http.ResponseWriter, r *http.Request) {
return return
} }
err = SyncUsers(ac)
if err != nil {
log.Error("su", err)
}
writeSuccessBytes(w, json) writeSuccessBytes(w, json)
} }
@ -240,6 +249,79 @@ func addUser(p request.Persister, a keycloakAuthRequest) (u entity.User, err err
return p.GetUser(userID) return p.GetUser(userID)
} }
// SyncUsers gets list of Keycloak users for specified Realm, Client Id
func SyncUsers(c keycloakConfig) (err error) {
form := url.Values{}
form.Add("username", c.AdminUser)
form.Add("password", c.AdminPassword)
form.Add("client_id", "admin-cli")
form.Add("grant_type", "password")
req, err := http.NewRequest("POST",
fmt.Sprintf("%s/realms/master/protocol/openid-connect/token", c.URL),
bytes.NewBufferString(form.Encode()))
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
req.Header.Add("Content-Length", strconv.Itoa(len(form.Encode())))
client := &http.Client{}
res, err := client.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
return err
}
ka := keycloakAPIAuth{}
err = json.Unmarshal(body, &ka)
if err != nil {
return err
}
if res.StatusCode != http.StatusOK {
return errors.New("Keycloak authentication failed " + res.Status)
}
req, err = http.NewRequest("GET",
fmt.Sprintf("%s/admin/realms/%s/users?max=500", c.URL, c.Realm),
nil)
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", ka.AccessToken))
client = &http.Client{}
res, err = client.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
body, err = ioutil.ReadAll(res.Body)
if err != nil {
return err
}
u := []keycloakUser{}
err = json.Unmarshal(body, &u)
if err != nil {
return err
}
if res.StatusCode != http.StatusOK {
return errors.New("Keycloak /users call failed " + res.Status)
}
log.Info(fmt.Sprintf("%d", res.StatusCode))
fmt.Println(fmt.Sprintf("%d len", len(u)))
fmt.Println(u[0].Email)
return nil
}
// Data received via Keycloak client library // Data received via Keycloak client library
type keycloakAuthRequest struct { type keycloakAuthRequest struct {
Domain string `json:"domain"` Domain string `json:"domain"`
@ -254,8 +336,25 @@ type keycloakAuthRequest struct {
// Keycloak server configuration // Keycloak server configuration
type keycloakConfig struct { type keycloakConfig struct {
URL string `json:"url"` URL string `json:"url"`
Realm string `json:"realm"` Realm string `json:"realm"`
ClientID string `json:"clientId"` ClientID string `json:"clientId"`
PublicKey string `json:"publicKey"` PublicKey string `json:"publicKey"`
AdminUser string `json:"adminUser"`
AdminPassword string `json:"adminPassword"`
}
// keycloakAPIAuth is returned when authenticating with Keycloak REST API.
type keycloakAPIAuth struct {
AccessToken string `json:"access_token"`
}
// keycloakUser details user record returned by Keycloak
type keycloakUser struct {
ID string `json:"id"`
Username string `json:"username"`
Email string `json:"email"`
Firstname string `json:"firstName"`
Lastname string `json:"lastName"`
Enabled bool `json:"enabled"`
} }