Ошибка аутентификации X-FACEBOOK-PLATFORM

Я пытаюсь подключиться к Facebook chat api через SMACK, используя приведенный ниже код, но всегда получаю X-FACEBOOK-PLATFORM failed: not-authorized. У меня есть действительный токен с разрешением xmpp, но я думаю, что что-то упускаю... он работает с пользователем/паролем, но не с accessToken.

Спасибо за вашу помощь, ребята, эта штука сводит меня с ума.

public class FacebookChatSample {

public static void main(   )
{

    String accessToken = //internet example "AAACjg0Eh1N8BAFuhUFZAN0EteV6pjZAsZAI46i8oV3iVmyLdaKiwaBcM5DPFjbEZAq9LZAZAA0qXsvaXkKB7SqnhubzlUAK7tmr3UYLaeQgaXSJ6EZCKn2G";
    String consumerKey = //internet example "179784128779487";

    long targetFacebookId = 550121201669650L;

    String toID = "1002221765";

    String message = "HELLOOOOO FROM MY JAVA PROGRAM!!";

    XMPPConnection connection = createXMPPConnection();
    try
    {
        connection.connect();
        connection.login( consumerKey, accessToken );

        String to = String.format( "-%[email protected]", Long.valueOf( targetFacebookId ) );
        Chat chat = connection.getChatManager().createChat( to, null );
        chat.sendMessage( message );
    }
    catch( XMPPException e )
    {
       e.printStackTrace();
    }
    finally
    {
        connection.disconnect();
    }
}

private static synchronized XMPPConnection createXMPPConnection()
{
    SASLAuthentication.registerSASLMechanism(
            SASLXFacebookPlatformMechanism.NAME,
            SASLXFacebookPlatformMechanism.class );
    SASLAuthentication.supportSASLMechanism(
            SASLXFacebookPlatformMechanism.NAME, 0 );

    ConnectionConfiguration configuration = new ConnectionConfiguration(
            "chat.facebook.com", 5222 );
    configuration.setSASLAuthenticationEnabled( true );

    return new XMPPConnection( configuration );
}

public static class SASLXFacebookPlatformMechanism extends SASLMechanism
{
    public static final String NAME = "X-FACEBOOK-PLATFORM";

    public SASLXFacebookPlatformMechanism(
            SASLAuthentication saslAuthentication )
    {
        super( saslAuthentication );
    }

    private String apiKey = "";

    private String accessToken = "";

    @Override
    protected void authenticate() throws IOException, XMPPException
    {
        AuthMechanism stanza = new AuthMechanism( getName(), null );
        getSASLAuthentication().send( stanza );
    }

    @SuppressWarnings( "hiding" )
    @Override
    public void authenticate( String apiKey, String host, String accessToken )
            throws IOException, XMPPException
    {
        if( apiKey == null || accessToken == null )
        {
            throw new IllegalStateException( "Invalid parameters!" );
        }

        this.apiKey = apiKey;
        this.accessToken = accessToken;
        this.hostname = host;

        String[] mechanisms = { "DIGEST-MD5" };
        Map<String, String> props = new HashMap<String, String>();
        this.sc = Sasl.createSaslClient( mechanisms, null, "xmpp", host,
                props, this );
        authenticate();
    }

    @Override
    public void authenticate( String username, String host,
            CallbackHandler cbh ) throws IOException, XMPPException
    {
        String[] mechanisms = { "DIGEST-MD5" };
        Map<String, String> props = new HashMap<String, String>();
        this.sc = Sasl.createSaslClient( mechanisms, null, "xmpp", host,
                props, cbh );
        authenticate();
    }

    @Override
    protected String getName()
    {
        return NAME;
    }

    @Override
    public void challengeReceived( String challenge ) throws IOException
    {
        byte response[] = null;
        if( challenge != null )
        {
            String decodedResponse = new String(
                    org.jivesoftware.smack.util.Base64.decode( challenge ) );
            Map<String, String> parameters = getQueryMap( decodedResponse );

            String version = "1.0";
            String nonce = parameters.get( "nonce" );
            String method = parameters.get( "method" );

            Long callId = Long.valueOf( System.currentTimeMillis() );

            String composedResponse = String
                    .format(
                            "method=%s&nonce=%s&access_token=%s&api_key=%s&call_id=%s&v=%s",
                            URLEncoder.encode( method, "UTF-8" ),
                            URLEncoder.encode( nonce, "UTF-8" ),
                            URLEncoder.encode( this.accessToken, "UTF-8" ),
                            URLEncoder.encode( this.apiKey, "UTF-8" ),
                            callId, URLEncoder.encode( version, "UTF-8" ) );
            response = composedResponse.getBytes();
        }

        String authenticationText = "";

        if( response != null )
        {
            authenticationText = org.jivesoftware.smack.util.Base64
                    .encodeBytes(
                            response,
                            org.jivesoftware.smack.util.Base64.DONT_BREAK_LINES );
        }

        Response stanza = new Response( authenticationText );

        getSASLAuthentication().send( stanza );
    }

    private Map<String, String> getQueryMap( String query )
    {
        String[] params = query.split( "&" );
        Map<String, String> map = new HashMap<String, String>();
        for( String param : params )
        {
            String name = param.split( "=" )[0];
            String value = param.split( "=" )[1];
            map.put( name, value );
        }
        return map;
    }
}
}

person Imanagent Sococare    schedule 26.09.2013    source источник


Ответы (1)


Боже мой, я тоже всю жизнь с этим борюсь. Я только что понял это! Как только я это понял, это казалось таким простым, но сбивает с толку то, что проблема, которая, кажется, исходит от XMPP, на самом деле проблема с Facebook. Я думаю, что ваша проблема (моя проблема заключалась в том, что Facebook требует, чтобы вы запрашивали определенные разрешения для входа в приложение, которые не имеют ничего общего с протоколом XMPP). Если вы посмотрите на спецификации Chat API, там говорится, что вам нужно запросить расширенное разрешение xmpp_login для вашего приложения, если вы используете X-FACEBOOK-PLATFORM. Вы должны сделать это через объект сеанса в SDK Facebook, который вы использовали для получения своего session_token.

Вот код, который я использовал:

session.requestNewReadPermissions(new NewPermissionsRequest(getActivity(), Arrays.asList("xmpp_login")));

Как только я это сделал, это сработало как шарм. Последнее предостережение заключается в том, что вам нужно убедиться, что всплывающее диалоговое окно с просьбой предоставить вашему приложению это расширенное разрешение появляется и получает необходимое разрешение ДО того, как вы перейдете к xmpp.login. В противном случае вы столкнетесь с той же проблемой, поскольку ваше приложение будет запрашивать разрешение, но фактически не получать разрешение.

Я надеюсь, что это работает для вас.

person JSv4    schedule 30.10.2013