Esempio n. 1
0
func (o *Oauth2) Revoke(ctx context.Context, req *oauth2.RevokeRequest, rsp *oauth2.RevokeResponse) error {
	// Who should be allowed to do this?

	if len(req.RefreshToken) > 0 {
		token, _, err := db.ReadRefresh(req.RefreshToken)
		if err != nil {
			if err == db.ErrNotFound {
				return errors.BadRequest("go.micro.srv.auth", "invalid_request")
			}
			return errors.InternalServerError("go.micro.srv.auth", "server_error")
		}

		if err := db.DeleteToken(req.AccessToken); err != nil {
			return errors.InternalServerError("go.micro.srv.auth", "server_error")
		}

		req.AccessToken = token.AccessToken
	}

	if len(req.AccessToken) == 0 {
		return errors.BadRequest("go.micro.srv.auth", "invalid_request")
	}

	if err := db.DeleteToken(req.AccessToken); err != nil {
		return errors.InternalServerError("go.micro.srv.auth", "server_error")
	}

	return nil
}
Esempio n. 2
0
func (o *Oauth2) Token(ctx context.Context, req *oauth2.TokenRequest, rsp *oauth2.TokenResponse) error {
	// We may actually need to authenticate who can make this request.
	// How should we do that?

	// TODO: track multiple attempts for the same authorization code and revoke all other tokens

	// supported grant types
	switch req.GrantType {
	case "authorization_code":
		// validate inputs
		if len(req.Code) == 0 || len(req.ClientId) == 0 || len(req.ClientSecret) == 0 {
			return errors.BadRequest("go.micro.srv.auth", "invalid_request")
		}

		// read authorization request
		storedReq, err := db.ReadRequest(req.Code)
		if err != nil {
			if err == db.ErrNotFound {
				return errors.BadRequest("go.micro.srv.auth", "invalid_request")
			} else {
				return errors.InternalServerError("go.micro.srv.auth", "server_error")
			}
		}
		// we have a request, is it the same client_id?
		if req.ClientId != storedReq.ClientId {
			return errors.BadRequest("go.micro.srv.auth", "invalid_request")
		}

		// is it the same redirect uri?
		if req.RedirectUri != storedReq.RedirectUri {
			return errors.BadRequest("go.micro.srv.auth", "invalid_request")
		}

		// auth
		if err := authClient(req.ClientId, req.ClientSecret); err != nil {
			return err
		}

		// ok successful auth

		// generate a token; tokens are basically opaque strings
		// we just hand back something random and base64 encoded
		token := &oauth2.Token{
			AccessToken:  db.Token(),
			TokenType:    "bearer",
			RefreshToken: db.Token(),
			ExpiresAt:    time.Now().Add(time.Hour).Unix(),
			Scopes:       storedReq.Scopes,
			Metadata:     req.Metadata,
		}

		// store the token against the client
		if err := db.CreateToken(token, req.ClientId, req.Code); err != nil {
			return errors.InternalServerError("go.micro.srv.auth", "server_error")
		}

		// return token
		rsp.Token = token
	case "client_credentials":
		// validate inputs
		if len(req.ClientId) == 0 || len(req.ClientSecret) == 0 {
			return errors.BadRequest("go.micro.srv.auth", "invalid_request")
		}

		// auth
		if err := authClient(req.ClientId, req.ClientSecret); err != nil {
			return err
		}

		// ok successful auth

		// generate a token; tokens are basically opaque strings
		// we just hand back something random and base64 encoded
		token := &oauth2.Token{
			AccessToken:  db.Token(),
			TokenType:    "bearer",
			RefreshToken: db.Token(),
			ExpiresAt:    time.Now().Add(time.Hour).Unix(),
			Scopes:       req.Scopes,
			Metadata:     req.Metadata,
		}

		// store the token against the client
		if err := db.CreateToken(token, req.ClientId, ""); err != nil {
			return errors.InternalServerError("go.micro.srv.auth", "server_error")
		}

		// return token
		rsp.Token = token
	case "refresh_token":
		// validate inputs
		if len(req.RefreshToken) == 0 || len(req.ClientId) == 0 || len(req.ClientSecret) == 0 {
			return errors.BadRequest("go.micro.srv.auth", "invalid_request")
		}

		// auth client
		if err := authClient(req.ClientId, req.ClientSecret); err != nil {
			return err
		}

		// get existing token
		token, clientId, err := db.ReadRefresh(req.RefreshToken)
		if err != nil {
			if err == db.ErrNotFound {
				return errors.BadRequest("go.micro.srv.auth", "invalid_request")
			}
			return errors.InternalServerError("go.micro.srv.auth", "server_error")
		}

		// client id does not match for refresh token
		if clientId != req.ClientId {
			return errors.BadRequest("go.micro.srv.auth", "access_denied")
		}

		// so we have a token, we now need to refresh

		id := token.AccessToken
		token.AccessToken = db.Token()
		token.RefreshToken = db.Token()
		token.ExpiresAt = time.Now().Add(time.Hour).Unix()

		// Update with new access token, refresh token and expiry
		// refresh expiry is set by db
		if err := db.UpdateToken(id, token); err != nil {
			return errors.InternalServerError("go.micro.srv.auth", "server_error")
		}

		rsp.Token = token
	default:
		return errors.BadRequest("go.micro.srv.auth", "unsupported_grant_type")
	}

	// Delete the authorization request when we successfully create a token
	if err := db.DeleteRequest(req.Code); err != nil {
		return errors.InternalServerError("go.micro.srv.auth", "server_error")
	}

	return nil
}