Client Dynamic Registration for native and in-browser apps

oauth

#1

Boa noite,

Primeiro gostaria de parabenizar o livro. Ficou muito bom e tirou muitas para a aplicação que estou desenvolvendo. Porém também me gerou novas dúvidas, hehe. Normal… Vamos a elas. Primeiro para confirmar que entendi direito e segundo garantir segurança.

O meu App será composto de dois back-ends:
1 - Authz Server
2 - Resource Server

E dois fronts
1 - SPA com Angular 2
2 - Aplicativos nativos, IOS e Android

Lendo o livro vi que não é indicado guardar o client secret, em nenhum desses fronts. O correto seria eu utilizar o Client Dynamic Registration, para obter o secret. Até que entendi certo ok?

Supondo que sim vamos para o próximo ponto.

Preciso garantir que só minhas aplicações consigam se registrar. Então principal dúvida é sobre isso. Como ter essa garantia?

Lendo a RFC 7591, ele falam sobre utilizar o parâmetro software_statement. Isso realmente vai garantir que só minha aplicação esta tentando se registrar?

Outra forma que vi é proteger o endpoint, necessitando assim de um token, que ao meu ver, após ser usado deve ser descartado. Como garantir que só minha aplicação vai ter esse token?

Esses códigos iriam ser distribuídos no meu app? Se sim, isso não seria o mesmo do que deixar o secret?


#2

Olá Vinícius.

Fico contente de saber que o livro te ajudou.
Quanto às suas dúvidas, elas realmente fazem todo sentido.

Vamos primeiro pensar no caso dos aplicativos nativos, ok? Em outubro desse ano, uma especificação focada em aplicativos nativos foi publicada como uma RFC. Trata-se da RFC 8252. Essa especificação aborda muita coisa interessante como uma forma legal de proteger o uso do authorization code através do mecanismo PKCE (vale a pena dar uma estudada nisso). Mas voltando ao nosso foco, realmente é complicado garantir que apenas os aplicativos oficiais se registrem em um Authorization Server específico.

Para tentar ajudar nisso, a seção 8.4 da RFC 8252 sugere algumas formas de tentar minimizar esse tipo de colisão no registro de clients nativos. Basicamente a especificação sugere duas coisas. Uma sugestão, é exigir o registro de um private-uri scheme baseado em um domínio sob controle do aplicativo como forma de tentar provar a propriedade da URI de redirecionamento. Outra sugestão é que o Authorization Server pode solicitar a inclusão de informações específicas que permitam que o Authorization Server identifique que o aplicativo é oficial (para fazer esse tipo de coisa, tudo vai depender da plataforma sendo usada - Android/iOS).

Agora pensando na solução SPA com Angular 2, eu sugiro que você use o grant type Implicit.

É interessante notar que é muito difícil ter uma aplicação totalmente segura. Quanto mais aumentarmos a segurança rumo a um ideal de 100%, iremos colocar mais barreiras diante do usuário (impactando na experiência do usuário). Portanto, na maioria das vezes (dependendo do cenário) o que podemos fazer é minimizar os impactos.

No caso do registro do aplicativo nativo através do mecanismo de registro dinâmico, o legal é que cada instância de aplicativo terá seu próprio secret (a RFC 8252 até sugere o uso do grant type Authorization Code). Tendo o próprio secret, se alguém conseguir roubar o secret de um aplicativo o impacto será bem menor se fosse descoberto um secret que vale para qualquer instância de Client.

No caso da aplicação SPA, ao usar o modo implícito, é importante que a duração do token seja pequena e que a URI de redirecionamento tenha sido registrada. Dependendo do caso será necessário decidir se o melhor não é usar o grant type authorization code e manter a conversa entre Client e Resource Server do lado do servidor (tudo isso vai depender do nível de segurança exigido para o que estiver sendo feito).

Bom, espero ter ajudado de alguma forma.

Abs


#3

Eu comecei a ler essa RFC 8252, mas me pareceu que ele foca mais na obtenção do token do resource owner do que no processo de registro dinâmico do client. E como a aplicação é própria a ideia é usar o grant type password.

Sobre as formas sugeridas para o Nativo.
O que seria o private-uri scheme? Tipo uma URL do app no celular?

Sobre as informações especificas. Quais seriam? Porque dependendo vai ficar no fonte também e podem ser roubadas certo?

Sobre o SPA.
O modo implicito traz um problema de usabilidade não? uma vez que não tem refresh token vou precisar ficar redirecionando o usuário no meio de uso?
Interessante saber que o Authorization Code também é uma opção válida. Dessa forma não impacta na experiência do usuário.


#4

Realmente a RFC 8252 tem como objetivo detalhar o uso de algumas boas práticas voltadas para o uso de browser externo para redirecionamento do usuário.

O private-uri scheme, também chamado de deep-link, é usado para que seu app possa ser iniciado a partir de uma URI. No Android por exemplo, você precisa criar configurar uma Activity no arquivo AndroidManifest.xml declarando algumas propriedades especiais dentro da tag intent-filter. Através desses atributos você define qual o scheme, host e o path conforme o exemplo abaixo:

<activity android:name=".teste.ActivityDeCallback">
    <intent-filter>
        <action android:name="android.intent.action.VIEW"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="android.intent.category.BROWSABLE"/>
        <data android:scheme="oauth"
            android:host="meu-app-de-teste"
            android:path="/redirect"/>
    </intent-filter>
</activity>

Dessa forma, se o usuário for redirecionado para oauth://meu-app-de-teste/redirect, a Activity ActivityDeCallback será carregada para o usuário.

Quanto as informações específicas infelizmente a RFC não ajuda muito mesmo. Como você disse, qualquer coisa que for extraída do próprio app pode ser recuperado caso seja realizada uma engenharia reversa do apk (no caso de Android).

Como não sou expert em mobile, vou deixar minha opinião pessoal sobre isso agora :slight_smile:
Caso um app malicioso se registrar no Authorization Server de forma dinâmica, a autorização do uso dos recursos só será realizada caso o Resource Owner instale um aplicativo que não seja oficial e ainda assim navegue por todo o fluxo de autorização.

Em todo caso, eu investigaria melhor a possibilidade de utilizar um token que possa ser obtido em um pré-cadastro da aplicação seguindo uma abordagem Protected Dynamic Client Registration. E para manter esse token seguro eu pesquisaria uma forma de guardar no Firebase, que acredito ter uma maneira segura de armazenar dados desse tipo.

Espero que essas dicas ajudem de alguma forma


#5

Interessante, não sabia que podíamos ter esse valor protegido, achei que teria que estar no código.

Pelo que tenho pesquisado. Nesse caso o ideal é gerar um token inicial que será usado pelos apps, com escopo apenas de criação de client. E os apps matem esse token protegido no firebase ou em algum local parecido (também não sou um expert em mobile). Então só poderá se registrar com ele. Funciona bem p o grant_type password.

Já para aplicação SPA que vai utilizar o grant_type authorization_code, deixo o client_id fixo, mas limito o cadastro para apenas client onde a redirect_uri aponte para meu domínio. Então mesmo que um client malicioso se cadastre, quando tentar acessar vai redirecionar para meu site mesmo. Aí usando junto o parâmetro code, não vai conseguir o acesso.

Legal. Gostei das abordagens. Muito obrigado pelas dicas.