我正在开发一个 ZenDesk 应用程序,它从后端系统中提取客户信息。我们需要使用 OAuth 2's browser-based authentication flow 对该系统进行身份验证。

包含到身份验证页面的链接没有问题,例如:

https://oauth2server.com/auth?
    response_type=token&
    client_id=CLIENT_ID&
    redirect_uri=REDIRECT_URI&
    scope=photos

但是,一旦用户登录,OAuth 服务器就会重定向客户端并包含授权 token 。所以 REDIRECT_URI 通常看起来像:
https://example.zendesk.com/agent/#token=ACCESS_TOKEN

但是,ZenDesk 已经使用片段标识符来指示要在页面上显示的内容:
https://example.zendesk.com/agent/#/dashboard
https://example.zendesk.com/agent/#/tickets/1234

我的 ZD App 只出现在某些页面上,所以我怎么才能同时出现
  • 让我的应用程序呈现并运行 Javascript,以及
  • 有可用的授权 token 的片段标识符吗?

  • (我确实可以控制后端 OAuth 服务器,因此如果您想不出一种干净的方法来完成此操作,也非常感谢 OAuth 服务器端 hack 建议。)

    最佳答案

    这是一个非常简单的 ZenDesk 应用程序(框架版本 0.5)

  • authenticates against Google(在单独的弹出窗口中)
  • 从当前可见的票证中获取 custom ticket field
  • retrieves the Google user's name

  • manifest.json 中,这个 ZenDesk 应用程序应该指定 "location": "ticket_sidebar"

    应用程序.js
    (function (window) {
        return {
            zenDeskSubdomain: 'YOUR_ZENDESK_SUBDOMAIN',
            googleClientId: 'YOUR_GOOGLE_CLIENT_ID',
    
            events: {
                'app.activated': 'onActivate',
                'app.deactivated': 'onDeactivate',
                'click .loginout': 'onLogInOutClick',
                'click .show-username': 'onShowUserNameClick'
            },
    
            requests: {
                getUserInfo: function (access_token) {
                    return {
                        url: 'https://www.googleapis.com/oauth2/v1/userinfo?access_token=' + access_token,
                        type: 'GET',
                        proxy_v2: true
                    };
                }
            },
    
            onActivate: function () {
                console.info("onActivate()");
                this.accessToken();
                var user_id = this.ticket().customField("custom_field_22931898");
                this.$('.userid').text(user_id);
            },
    
            onDeactivate: function () {
                console.info("onDeactivate()");
                if (this.timer) {
                    clearTimeout(this.timer);
                }
            },
    
            onShowUserNameClick: function () {
                var access_token = this.accessToken();
    
                if (!access_token) {
                    console.info("Can't do it!  No access_token!");
                    return;
                }
    
                this.ajax('getUserInfo', access_token)
                    .done(function (data) {
                        console.info(data);
                        this.$('.username').text(data.name);
                    });
            },
    
            onLogInOutClick: function (event) {
                if (this.accessToken()) {
                    this.logout(event);
                } else {
                    this.login(event);
                }
            },
    
            login: function (event) {
                console.info("login()");
                event.preventDefault();
                var popup = this.createLoginPopup();
                this.awaitAccessToken(popup);
            },
    
            logout: function (event) {
                console.info("logout()");
                event.preventDefault();
                this.accessToken(null);
                console.info("  access_token = " + this.accessToken());
                this.$('.loginout').text('login');
            },
    
            createLoginPopup: function () {
                console.info("createLoginPopup()");
                return window.open(
                'https://accounts.google.com/o/oauth2/auth?response_type=token&client_id=' + this.googleClientId + '&redirect_uri=https%3A%2F%2F' + this.zenDeskSubdomain + '.zendesk.com%2Fagent%2F&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile',
                'Login Popup',
                'width=400,height=400');
            },
    
            timer: null,
            awaitAccessToken: function (popup) {
                console.info("awaitAccessToken()");
                if (this.isLoaded(popup)) {
                    console.info("  popup is loaded");
                } else {
                    console.info("  popup is NOT loaded; sleeping");
                    var t = this;
                    this.timer = setTimeout(
                        function () { t.awaitAccessToken(popup); },
                        1000);
                    return;
                }
    
                var access_token = this.parseAccessToken(popup.location.href);
    
                if (access_token) {
                    console.info('  access_token = ' + access_token);
                    popup.close();
                    this.accessToken(access_token);
                } else {
                    services.notify('Error requesting code...');
                }
            },
    
            isLoaded: function (win) {
                try {
                    return ('about:blank' !== win.location.href)
                        && (null !== win.document.body.innerHTML);
                } catch (err) {
                    return false;
                }
            },
    
            parseAccessToken: function (uri) {
                var match = uri.match(/[#&]access_token=([^&]*)/i);
                return match[1] || null;
            },
    
            accessToken: function (value) {
                if (1 === arguments.length) {
                    console.info("Storing access_token = " + value);
                    this.store({ access_token: value });
                }
    
                var token = this.store('access_token');
                console.info("access_token = " + value);
    
                var loginout = this.$('.loginout');
                if (token) {
                    loginout.text('logout');
                } else {
                    loginout.text('login');
                }
    
                return token;
            }
        };
    }(this));
    

    布局.hdbs
    <header>
      <span class="logo"/>
      <h3>{{setting "name"}}</h3>
    </header>
    <section data-main/>
    <footer>
        <div><a class="loginout">login</a></div>
        <div><a class="show-username">show username</a></div>
        <div><b>user id: </b><span class="userid">unknown</span></div>
        <div><b>username: </b><span class="username">unknown</span></div>
    </footer>
    

    谷歌 OAuth 配置

    配置 Google OAuth 以允许来自您的应用程序的流量。

    重定向 URI
  • http://localhost:XXX - 用于 ZAT 开发/测试环境
  • https://YOUR_ZENDESK_SUBDOMAIN.zendesk.com/agent/ - 用于生产

  • Javascript 起源
  • http://localhost:XXX - 用于 ZAT 开发/测试环境
  • https://YOUR_ZENDESK_SUBDOMAIN.zendesk.com - 用于生产
  • 关于javascript - ZenDesk App OAuth 基于浏览器的身份验证,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/18233252/

    10-11 05:57