Programing

RESTful 인증

lottogame 2020. 9. 30. 08:33
반응형

RESTful 인증


RESTful 인증은 무엇을 의미하며 어떻게 작동합니까? Google에서 좋은 개요를 찾을 수 없습니다. 내 유일한 이해는 URL에 세션 키 (기억)를 전달한다는 것입니다.하지만 이것은 끔찍하게 잘못되었을 수 있습니다.


RESTful 클라이언트-서버 아키텍처에서 인증을 처리하는 방법은 논쟁의 여지가 있습니다.

일반적으로 SOA over HTTP 세계에서 다음을 통해 달성 할 수 있습니다.

  • HTTPS를 통한 HTTP 기본 인증;
  • 쿠키 및 세션 관리
  • HTTP 헤더의 토큰 (예 : OAuth 2.0 + JWT)
  • 추가 서명 매개 변수가있는 쿼리 인증.

기껏해야 소프트웨어 아키텍처와 일치하도록 이러한 기술을 적용하거나 더 잘 혼합해야합니다.

각 인증 체계에는 보안 정책 및 소프트웨어 아키텍처의 목적에 따라 고유 한 장점과 단점이 있습니다.

HTTPS를 통한 HTTP 기본 인증

표준 HTTPS 프로토콜을 기반으로하는이 첫 번째 솔루션은 대부분의 웹 서비스에서 사용됩니다.

GET /spec.html HTTP/1.1
Host: www.example.org
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

구현하기 쉽고 기본적으로 모든 브라우저에서 사용할 수 있지만 브라우저에 표시되는 끔찍한 인증 창과 같은 몇 가지 알려진 단점이 있습니다. 사용자 이름과 암호가 서버로 전송된다는 사실 (HTTPS를 통해) (암호가 키보드 입력 중에 클라이언트 측에만 유지되고 서버에 보안 해시로 저장되도록하는 것이 더 안전해야 함) .

Digest Authentication을 사용할 수 있지만 MiM 또는 Replay 공격에 취약 하고 HTTP에만 해당 하므로 HTTPS도 필요합니다 .

쿠키를 통한 세션

솔직히 말해서 서버에서 관리되는 세션은 진정한 Stateless가 아닙니다.

한 가지 가능성은 쿠키 콘텐츠 내에 모든 데이터를 유지하는 것입니다. 그리고 설계 상 쿠키는 서버 측에서 처리됩니다 (실제로 클라이언트는이 쿠키 데이터를 해석하려고 시도하지도 않습니다. 각 연속 요청시 서버에 다시 전달합니다). 그러나이 쿠키 데이터는 애플리케이션 상태 데이터이므로 클라이언트는 순수한 Stateless 세계에서 서버가 아닌이를 관리해야합니다.

GET /spec.html HTTP/1.1
Host: www.example.org
Cookie: theme=light; sessionToken=abc123

쿠키 기술 자체는 HTTP로 연결되어 있으므로 프로토콜에 독립적 인 IMHO 여야하는 진정한 RESTful이 아닙니다. MiM 또는 Replay 공격에 취약합니다 .

토큰 (OAuth2)을 통해 부여됨

대안은 HTTP 헤더 내에 토큰을 넣어 요청이 인증되도록하는 것입니다. 예를 들어 이것이 OAuth 2.0이하는 일입니다. RFC 6749를 참조하십시오 .

 GET /resource/1 HTTP/1.1
 Host: example.com
 Authorization: Bearer mF_9.B5f-4.1JqM

요컨대 쿠키와 매우 유사하며 상태 비 저장이 아니라 HTTP 전송 세부 정보에 의존하고 MiM 및 Replay를 포함한 많은 보안 약점 에 따라 동일한 문제가 발생 하므로 HTTPS를 통해서만 사용해야합니다. 일반적으로 JWT 가 토큰으로 사용됩니다.

쿼리 인증

쿼리 인증은 URI의 몇 가지 추가 매개 변수를 통해 각 RESTful 요청에 서명하는 것으로 구성됩니다. 참조 이 참조 문서를 .

이 기사에서는 다음과 같이 정의되었습니다.

모든 REST 쿼리는 개인 자격 증명을 서명 토큰으로 사용하여 소문자 알파벳 순서로 정렬 된 쿼리 매개 변수에 서명하여 인증해야합니다. 쿼리 문자열을 URL 인코딩하기 전에 서명해야합니다.

이 기술은 Stateless 아키텍처와 더 호환 될 수 있으며 가벼운 세션 관리 (DB 지속성 대신 메모리 내 세션 사용)로 구현할 수도 있습니다.

예를 들어, 다음은 위 링크의 일반 URI 샘플입니다.

GET /object?apiKey=Qwerty2010

다음과 같이 전송되어야합니다.

GET /object?timestamp=1261496500&apiKey=Qwerty2010&signature=abcdef0123456789

서명되는 문자열은 /object?apikey=Qwerty2010&timestamp=1261496500이고 서명은 API 키의 개인 구성 요소를 사용하는 해당 문자열의 SHA256 해시입니다.

서버 측 데이터 캐싱은 항상 사용할 수 있습니다. 예를 들어 프레임 워크에서는 URI 수준이 아닌 SQL 수준에서 응답을 캐시합니다. 따라서이 추가 매개 변수를 추가해도 캐시 메커니즘이 깨지지는 않습니다.

JSON 및 REST를 기반으로하는 클라이언트-서버 ORM / SOA / MVC 프레임 워크의 RESTful 인증에 대한 자세한 내용은 이 문서참조하십시오 . HTTP / 1.1뿐만 아니라 명명 된 파이프 또는 GDI 메시지 (로컬)를 통한 통신도 허용하기 때문에 HTTP 특수성 (예 : 헤더 또는 쿠키)에 의존하지 않고 진정한 RESTful 인증 패턴을 구현하려고했습니다.

나중에 참고 : URI에 서명을 추가하는 것은 나쁜 습관으로 보일 수 있으므로 (예를 들어 http 서버 로그에 나타나기 때문에) 재생을 방지하기 위해 적절한 TTL로 완화해야합니다. 그러나 http 로그가 손상되면 확실히 더 큰 보안 문제가 발생합니다.

실제로, OAuth 2.0에 대한 향후 MAC 토큰 인증은 현재 "토큰에 의해 부여됨"체계와 관련하여 크게 개선 될 수 있습니다. 그러나 이것은 여전히 ​​진행중인 작업이며 HTTP 전송과 관련이 있습니다.

결론

REST는 실제로는 대부분 HTTP를 통해 구현되는 경우에도 HTTP 기반 일뿐 아니라는 결론을 내릴 가치가 있습니다. REST는 다른 통신 계층을 사용할 수 있습니다. 따라서 RESTful 인증은 Google이 어떤 답변을하든 HTTP 인증의 동의어가 아닙니다. HTTP 메커니즘을 전혀 사용해서는 안되지만 통신 계층에서 추상화되어야합니다. 그리고 HTTP 통신을 사용하는 경우 Let 's Encrypt 이니셔티브 덕분에 인증 체계에 추가로 필요한 적절한 HTTPS를 사용하지 않을 이유가 없습니다.


열광적으로 "HTTP 인증"을 외치는 사람들이 REST (컴퓨터 간 웹 서비스 대신)를 사용하여 브라우저 기반 응용 프로그램을 만들려고 시도했는지 의심됩니다. .

브라우저에서 볼 HTML 페이지를 생성하는 RESTful 서비스에서 HTTP 인증을 사용할 때 발견 된 문제는 다음과 같습니다.

  • 사용자는 일반적으로 매우 사용자 친화적이지 않은보기 흉한 브라우저로 만든 로그인 상자를받습니다. 암호 검색, 도움말 상자 등을 추가 할 수 없습니다.
  • 로그 아웃하거나 다른 이름으로 로그인하는 것이 문제입니다. 브라우저는 창을 닫을 때까지 사이트에 인증 정보를 계속 보냅니다.
  • 타임 아웃은 어렵다

이러한 점을 하나씩 다루는 매우 통찰력있는 기사가 여기 에 있지만 이로 인해 많은 브라우저 별 자바 스크립트 해커, 해결 방법 등이 발생합니다. 따라서 이전 버전과도 호환되지 않으므로 새 브라우저가 출시되면 지속적인 유지 관리가 필요합니다. 깨끗하고 명확한 디자인을 고려하지 않고, 친구들에게 내 REST 배지를 열정적으로 보여줄 수 있도록 많은 추가 작업과 골칫거리라고 생각합니다.

나는 쿠키가 해결책이라고 믿습니다. 하지만 잠깐, 쿠키는 사악하지 않습니까? 아니요, 그렇지 않습니다. 쿠키가 자주 사용되는 방식은 악합니다. 쿠키 자체는 브라우저가 검색하는 동안 추적하는 HTTP 인증 정보와 마찬가지로 클라이언트 측 정보의 일부입니다. 그리고이 클라이언트 측 정보는 HTTP 인증 정보와 마찬가지로 요청이있을 때마다 서버로 전송됩니다. 개념적으로 유일한 차이점은 이 클라이언트 측 상태 내용응답의 일부로 서버에 의해 결정될 수 있다는 것 입니다.

다음 규칙만으로 세션을 RESTful 리소스로 만듭니다.

  • 세션은 사용자 ID에 대한 키 (및 시간 제한을위한 마지막 액션 타임 스탬프를) 매핑
  • 경우 세션이 존재하고 키가 유효 그 수단이다.
  • 로그인은 / sessions에 게시하는 것을 의미하며 새 키는 쿠키로 설정됩니다.
  • 로그 아웃은 / sessions / {key} 삭제를 의미합니다 (오버로드 된 POST로, 우리는 브라우저이고 HTML 5는 아직 갈 길이 멀다는 것을 기억하십시오)
  • 인증은 모든 요청에서 키를 쿠키로 전송하고 세션이 존재하고 유효한지 확인하여 수행됩니다.

이제 HTTP 인증과의 유일한 차이점은 인증 키가 서버에서 생성되어 클라이언트가 입력 한 자격 증명에서 계산하는 대신 계속해서 다시 보내는 클라이언트로 전송된다는 것입니다.

converter42는 https를 사용할 때 (우리가해야하는) 쿠키가 보안 플래그를 설정하여 인증 정보가 비보안 연결을 통해 전송되지 않도록하는 것이 중요하다고 덧붙입니다. 좋은 지적, 직접 본 적이 없었습니다.

나는 이것이 잘 작동하는 충분한 솔루션이라고 생각하지만, 나는이 체계의 잠재적 인 허점을 식별 할 수있는 보안 전문가가 충분하지 않다는 것을 인정해야합니다. 내가 아는 것은 수백 개의 비 RESTful 웹 애플리케이션이 본질적으로 동일한 것을 사용한다는 것입니다. 로그인 프로토콜 (PHP의 $ _SESSION, Java EE의 HttpSession 등). 쿠키 헤더 내용은 번역 리소스 등에 액세스하기 위해 accept-language를 사용할 수있는 것처럼 단순히 서버 측 리소스를 주소 지정하는 데 사용됩니다. 똑같다고 생각하지만 다른 사람은 아닐까요? 여러분 어떻게 생각하세요?


Enough already is said on this topic by good folks here. But here is my 2 cents.

There are 2 modes of interaction:

  1. human-to-machine (HTM)
  2. machine-to-machine (MTM)

The machine is the common denominator, expressed as the REST APIs, and the actors/clients being either the humans or the machines.

Now, in a truly RESTful architecture, the concept of statelessness implies that all relevant application states (meaning the client side states) must be supplied with each and every request. By relevant, it is meant that whatever is required by the REST API to process the request and serve an appropriate response.

When we consider this in the context of human-to-machine applications, "browser-based" as Skrebbel points out above, this means that the (web) application running in the browser will need to send its state and relevant information with each request it makes to the back end REST APIs.

Consider this: You have a data/information platform exposed asset of REST APIs. Perhaps you have a self-service BI platform that handles all the data cubes. But you want your (human) customers to access this via (1) web app, (2) mobile app, and (3) some 3rd party application. In the end, even chain of MTMs leads up to HTM - right. So human users remain at the apex of information chain.

In the first 2 cases, you have a case for human-to-machine interaction, the information being actually consumed by a human user. In the last case, you have a machine program consuming the REST APIs.

The concept of authentication applies across the board. How will you design this so that your REST APIs are accessed in a uniform, secured manner? The way I see this, there are 2 ways:

Way-1:

  1. There is no login, to begin with. Every request performs the login
  2. The client sends its identifying parameters + the request specific parameters with each request
  3. The REST API takes them, turns around, pings the user store (whatever that is) and confirms the auth
  4. If the auth is established, services the request; otherwise, denies with appropriate HTTP status code
  5. Repeat the above for every request across all the REST APIs in your catalog

Way-2:

  1. The client begins with an auth request
  2. A login REST API will handle all such requests
  3. It takes in auth parameters (API key, uid/pwd or whatever you choose) and verifies auth against the user store (LDAP, AD, or MySQL DB etc.)
  4. If verified, creates an auth token and hands it back to the client/caller
  5. The caller then sends this auth token + request specific params with every subsequent request to other business REST APIs, until logged out or until the lease expires

Clearly, in Way-2, the REST APIs will need a way to recognize and trust the token as valid. The Login API performed the auth verification, and therefore that "valet key" needs to be trusted by other REST APIs in your catalog.

This, of course, means that the auth key/token will need to be stored and shared among the REST APIs. This shared, trusted token repository can be local/federated whatever, allowing REST APIs from other organizations to trust each other.

But I digress.

The point is, a "state" (about the client's authenticated status) needs to be maintained and shared so that all REST APIs can create a circle of trust. If we do not do this, which is the Way-1, we must accept that an act of authentication must be performed for any/all requests coming in.

Performing authentication is a resource-intensive process. Imagine executing SQL queries, for every incoming request, against your user store to check for uid/pwd match. Or, to encrypt and perform hash matches (the AWS style). And architecturally, every REST API will need to perform this, I suspect, using a common back-end login service. Because, if you don't, then you litter the auth code everywhere. A big mess.

So more the layers, more latency.

Now, take Way-1 and apply to HTM. Does your (human) user really care if you have to send uid/pwd/hash or whatever with every request? No, as long as you don't bother her by throwing the auth/login page every second. Good luck having customers if you do. So, what you will do is to store the login information somewhere on the client side, in the browser, right at the beginning, and send it with every request made. For the (human) user, she has already logged in, and a "session" is available. But in reality, she is authenticated on every request.

Same with Way-2. Your (human) user will never notice. So no harm was done.

What if we apply Way-1 to MTM? In this case, since its a machine, we can bore the hell out of this guy by asking it submit authentication information with every request. Nobody cares! Performing Way-2 on MTM will not evoke any special reaction; its a damn machine. It could care less!

So really, the question is what suits your need. Statelessness has a price to pay. Pay the price and move on. If you want to be a purist, then pay the price for that too, and move on.

In the end, philosophies do not matter. What really matters is information discovery, presentation, and the consumption experience. If people love your APIs, you did your job.


Here is a truly and completely RESTful authentication solution:

  1. Create a public/private key pair on the authentication server.
  2. Distribute the public key to all servers.
  3. When a client authenticates:

    3.1. issue a token which contains the following:

    • Expiration time
    • users name (optional)
    • users IP (optional)
    • hash of a password (optional)

    3.2. Encrypt the token with the private key.

    3.3. Send the encrypted token back to the user.

  4. When the user accesses any API they must also pass in their auth token.

  5. Servers can verify that the token is valid by decrypting it using the auth server's public key.

This is stateless/RESTful authentication.

Note, that if a password hash were included the user would also send the unencrypted password along with the authentication token. The server could verify that the password matched the password that was used to create the authentication token by comparing hashes. A secure connection using something like HTTPS would be necessary. Javascript on the client side could handle getting the user's password and storing it client side, either in memory or in a cookie, possibly encrypted with the server's public key.


To be honest with you I've seen great answers here but something that bothers me a bit is when someone will take the whole Stateless concept to a extreme where it becomes dogmatic. It reminds me of those old Smalltalk fans that only wanted to embrace pure OO and if something is not an object, then you're doing it wrong. Give me a break.

The RESTful approach is supposed to make your life easier and reduce the overhead and cost of sessions, try to follow it as it is a wise thing to do, but the minute you follow a discipline (any discipline/guideline) to the extreme where it no longer provides the benefit it was intended for, then you're doing it wrong. Some of the best languages today have both, functional programming and object orientation.

If the easiest way for you to solve your problem is to store the authentication key in a cookie and send it on HTTP header, then do it, just don't abuse it. Remember that sessions are bad when they become heavy and big, if all your session consists of is a short string containing a key, then what's the big deal?

I am open to accept corrections in comments but I just don't see the point (so far) in making our lives miserable to simply avoid keeping a big dictionary of hashes in our server.


First and foremost, a RESTful web service is STATELESS (or in other words, SESSIONLESS). Therefore, a RESTful service does not have and should not have a concept of session or cookies involved. The way to do authentication or authorization in the RESTful service is by using the HTTP Authorization header as defined in the RFC 2616 HTTP specifications. Every single request should contain the HTTP Authorization header, and the request should be sent over an HTTPs (SSL) connection. This is the correct way to do authentication and to verify the authorization of requests in a HTTP RESTful web services. I have implemented a RESTful web service for the Cisco PRIME Performance Manager application at Cisco Systems. And as part of that web service, I have implemented authentication/authorization as well.


It's certainly not about "session keys" as it is generally used to refer to sessionless authentication which is performed within all of the constraints of REST. Each request is self-describing, carrying enough information to authorize the request on its own without any server-side application state.

The easiest way to approach this is by starting with HTTP's built-in authentication mechanisms in RFC 2617.


The 'very insightful' article mentioned by @skrebel ( http://www.berenddeboer.net/rest/authentication.html ) discusses a convoluted but really broken method of authentication.

You may try to visit the page (which is supposed to be viewable only to authenticated user) http://www.berenddeboer.net/rest/site/authenticated.html without any login credentials.

(Sorry I can't comment on the answer.)

I would say REST and authentication simply do not mix. REST means stateless but 'authenticated' is a state. You cannot have them both at the same layer. If you are a RESTful advocate and frown upon states, then you have to go with HTTPS (i.e. leave the security issue to another layer).


I think restful authentication involves the passing of an authentication token as a parameter in the request. Examples are the use of apikeys by api's. I don't believe the use of cookies or http auth qualifies.


Update on 16-Feb-2019

The approach mentioned earlier below is essentially "Resource Owner Password Credential" grant type of OAuth2.0. This is an easy way to get up and running. However, with this approach every application in the organization will end up with its own authentication and authorization mechanisms. The recommended approach is "Authorization Code" grant type. Additionally, in my earlier answer below I recommended browser localStorage for storing auth tokens. However, I've come to believe that cookie is the right option for this purpose. I have detailed my reasons, authorization code grant type implementation approach, security considerations etc. in this StackOverflow answer.


I think the following approach can be used for REST service authentication:

  1. Create a login RESTful API to accept username and password for authentication. Use HTTP POST method to prevent caching and SSL for security during transit On successful authentication, the API returns two JWTs - one access token (shorter validity, say 30 minutes) and one refresh token (longer validity, say 24 hours)
  2. The client (a web based UI) stores the JWTs in local storage and in every subsequent API call passes the access token in "Authorization: Bearer #access token" header
  3. The API checks the validity of the token by verifying the signature and expiry date. If the token is valid, check if the user (It interprets the "sub" claim in JWT as username) has access to the API with a cache lookup. If the user is authorized to access the API, execute the business logic
  4. If the token is expired, the API returns HTTP response code 400
  5. The client, on receiving 400/401, invokes another REST API with the refresh token in "Authorization: Bearer #refresh token" header to get a new access token.
  6. On receiving the call with refresh token, check if the refresh token is valid by checking the signature and the expiry date. If the refresh token is valid, refresh the access right cache of the user from DB and return new access token and refresh token. If the refresh token is invalid, return HTTP response code 400
  7. If a new access token and refresh token are returned, go to step 2. If HTTP response code 400 is returned, the client assumes that the refresh token has expired and asks for username and password from the user
  8. For logout, purge the local storage

With this approach we are doing the expensive operation of loading the cache with user specific access right details every 30 minutes. So if an access is revoked or new access is granted, it takes 30 minutes to reflect or a logout followed by a login.


That's the way to do that: Using OAuth 2.0 for Login.

You may use other authentication methods other then Google's as long as it supports OAuth.


To answer this question from my understanding...

An authentication system that uses REST so that you do not need to actually track or manage the users in your system. This is done by using the HTTP methods POST, GET, PUT, DELETE. We take these 4 methods and think of them in terms of database interaction as CREATE, READ, UPDATE, DELETE (but on the web we use POST and GET because that is what anchor tags support currently). So treating POST and GET as our CREATE/READ/UPDATE/DELETE (CRUD) then we can design routes in our web application that will be able to deduce what action of CRUD we are achieving.

For example, in a Ruby on Rails application we can build our web app such that if a user who is logged in visits http://store.com/account/logout then the GET of that page can viewed as the user attempting to logout. In our rails controller we would build an action in that logs the user out and sends them back to the home page.

A GET on the login page would yield a form. a POST on the login page would be viewed as a login attempt and take the POST data and use it to login.

To me, it is a practice of using HTTP methods mapped to their database meaning and then building an authentication system with that in mind you do not need to pass around any session id's or track sessions.

I'm still learning -- if you find anything I have said to be wrong please correct me, and if you learn more post it back here. Thanks.


Using a Public key infrastruction in which the registration of a key involves proper binding ensures that the public key is bound to the individual to which it is assigned in a way that ensures non-repudiation

See http://en.wikipedia.org/wiki/Public_key_infrastructure . If you follow the proper PKI standards, the person or agent who improperly uses the stolen key can be identified and locked out. If the agent is required to use a certificate, the binding gets pretty tight. A clever and quick-moving thief can escape, but they leave more crumbs.


Tips valid for securing any web application

If you want to secure your application, then you should definitely start by using HTTPS instead of HTTP, this ensures a creating secure channel between you & the users that will prevent sniffing the data sent back & forth to the users & will help keep the data exchanged confidential.

You can use JWTs (JSON Web Tokens) to secure RESTful APIs, this has many benefits when compared to the server-side sessions, the benefits are mainly:

1- More scalable, as your API servers will not have to maintain sessions for each user (which can be a big burden when you have many sessions)

2- JWTs are self contained & have the claims which define the user role for example & what he can access & issued at date & expiry date (after which JWT won't be valid)

3- Easier to handle across load-balancers & if you have multiple API servers as you won't have to share session data nor configure server to route the session to same server, whenever a request with a JWT hit any server it can be authenticated & authorized

4- Less pressure on your DB as well as you won't have to constantly store & retrieve session id & data for each request

5- The JWTs can't be tampered with if you use a strong key to sign the JWT, so you can trust the claims in the JWT that is sent with the request without having to check the user session & whether he is authorized or not, you can just check the JWT & then you are all set to know who & what this user can do.

Many libraries provide easy ways to create & validate JWTs in most programming languages, for example: in node.js one of the most popular is jsonwebtoken

Since REST APIs generally aims to keep the server stateless, so JWTs are more compatible with that concept as each request is sent with Authorization token that is self contained (JWT) without the server having to keep track of user session compared to sessions which make the server stateful so that it remembers the user & his role, however, sessions are also widely used & have their pros, which you can search for if you want.

One important thing to note is that you have to securely deliver the JWT to the client using HTTPS & save it in a secure place (for example in local storage).

You can learn more about JWTs from this link

참고URL : https://stackoverflow.com/questions/319530/restful-authentication

반응형